如何通过雪花算法用Python实现一个简单的发号器


Posted in Python onJuly 03, 2019

实现一个简单的发号器

根据snowflake算法的原理实现一个简单的发号器,产生不重复、自增的id。

1.snowflake算法的简单描述

如何通过雪花算法用Python实现一个简单的发号器

这里的snowflake算法是用二进制的,有64位。其中41位的时间戳表示:当前时间戳减去某个设定的起始时间,10位标识表示:不同的机器、数据库的标识ID等等,序列号为每秒或每毫秒内自增的id。

我做的时候没有用位运算去实现,而是做了一个十进制的,16位的(当时项目要求是16位的)。但是实现发号器的基本策略是一样的,通过时间戳和标识来防止重复,通过序列号实现自增。当然啦,重点不是发号器多少位,而是根据项目的实际情况,利用snowflake算法的原理,实现一个适合自己项目的发号器。

2.Python实现

时间戳:9位,起始时间为2018-01-01 00:00:00 ,时间戳为当前时间减去起始时间。时间戳有9为,可用时间为 999999999/(606024*365)≈31(年)。

标识ID:2位,我用的时候比较简单,只是涉及一个数据库的情况,所以用一张数据表对应一个标识ID,可用100张表。

序列号:5位,我时间戳用的是秒级的,但是5位是10万个序列号,经过测试在一秒内是完全够用的。

所以时间戳、标识ID、序列号的位数也没规定说一定要多少,根据自己项目的实际来即可。

代码如下:

import time
class MySnow:
  def __init__(self,dataID):
    self.start = int(time.mktime(time.strptime('2018-01-01 00:00:00', "%Y-%m-%d %H:%M:%S")))
    self.last = int(time.time())
    self.countID = 0
    self.dataID = dataID  # 数据ID,这个自定义或是映射

  def get_id(self):
    # 时间差部分
    now = int(time.time())
    temp = now-self.start
    if len(str(temp)) < 9: # 时间差不够9位的在前面补0
      length = len(str(temp))
      s = "0" * (9-length)
      temp = s + str(temp)
    if now == self.last:
      self.countID += 1  # 同一时间差,序列号自增
    else:
      self.countID = 0  # 不同时间差,序列号重新置为0
      self.last = now
    # 标识ID部分
    if len(str(self.dataID)) < 2:
      length = len(str(self.dataID))
      s = "0" * (2-length)
      self.dataID = s + str(self.dataID)
    # 自增序列号部分
    if self.countID == 99999: # 序列号自增5位满了,睡眠一秒钟
      time.sleep(1)
    countIDdata = str(self.countID)
    if len(countIDdata) < 5: # 序列号不够5位的在前面补0
      length = len(countIDdata)
      s = "0"*(5-length)
      countIDdata = s + countIDdata
    id = str(temp) + str(self.dataID) + countIDdata
    return id

使用方法:

snow = MySnow(dataID="00")
print(snow.get_id())

其中dataID即为标识ID,countID为自增序列号。dataID可以一个通过自定义的映射表获得,这个视实际的项目情况而定。

3.关于并发

首先,直接用这个发号器是不能进行并发操作,会产生重复的id。如果真的要进行并发,那么就要权衡一下并发和位数的哪个更重要了!

拿实际例子来说吧,比如我并发的目的是为了节省时间,让程序更快的跑完,这时候为了并发,我把dataID中拿出一位来,标识不同的子进程,这样可以防止产生重复的id。但是实际上这用了位数去换取时间,如果是id位数比较少的情况,比如16位的,dataID比较少,我个人认为这样是不值得的,有些奢侈。这时候便是位数比并发重要啦。

当时如果位数充裕,比如20位的,需要并发就并发啦。

还有一种实现并发的方法,就是给发号器加锁,发号的时候加锁,发完了解锁。这个我没有试过,有兴趣的可以试一下哈哈。但是我有个疑惑啊,就是不断加锁和解锁切换,带来的时间和资源开销会不会很大呢。

Python 相关文章推荐
Python SQLite3数据库操作类分享
Jun 10 Python
Python编程中的反模式实例分析
Dec 08 Python
Python操作MySQL数据库9个实用实例
Dec 11 Python
tensorflow建立一个简单的神经网络的方法
Feb 10 Python
Python批量提取PDF文件中文本的脚本
Mar 14 Python
Python操作配置文件ini的三种方法讲解
Feb 22 Python
Django框架 Pagination分页实现代码实例
Sep 04 Python
Python pysnmp使用方法及代码实例
Aug 24 Python
python爬取企查查企业信息之selenium自动模拟登录企查查
Apr 08 Python
python 中[0]*2与0*2的区别说明
May 10 Python
pytorch 实现多个Dataloader同时训练
May 29 Python
利用python调用摄像头的实例分析
Jun 07 Python
Python实现个人微信号自动监控告警的示例
Jul 03 #Python
python pandas模块基础学习详解
Jul 03 #Python
python将excel转换为csv的代码方法总结
Jul 03 #Python
pandas实现to_sql将DataFrame保存到数据库中
Jul 03 #Python
python实现控制COM口的示例
Jul 03 #Python
python pandas时序处理相关功能详解
Jul 03 #Python
在linux下实现 python 监控usb设备信号
Jul 03 #Python
You might like
PHP ajax 分页类代码
2008/11/13 PHP
解析php二分法查找数组是否包含某一元素
2013/05/23 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
ThinkPHP简单使用memcache缓存的方法
2016/11/15 PHP
ThinkPHP中获取指定日期后工作日的具体日期方法
2018/10/14 PHP
在js中使用&quot;with&quot;语句中跨frame的变量引用问题
2007/03/08 Javascript
jQuery Selector选择器小结
2010/05/06 Javascript
jQuery EasyUI API 中文文档 - DataGrid数据表格
2011/11/17 Javascript
javascript中如何处理引号编码&amp;#034;
2013/08/15 Javascript
如何将网页表格内容导入excel
2014/02/18 Javascript
对new functionName()定义一个函数的理解
2014/05/22 Javascript
bootstrap-treeview自定义双击事件实现方法
2016/01/09 Javascript
浅析jquery数组删除指定元素的方法:grep()
2016/05/19 Javascript
微信小程序 五星评价功能的实现
2017/03/09 Javascript
利用Node.js对文件进行重命名
2017/03/12 Javascript
JavaScript实现表单注册、表单验证、运算符功能
2018/10/15 Javascript
JavaScript多种页面刷新方法小结
2019/04/04 Javascript
jquery validate 实现动态增加/删除验证规则操作示例
2019/10/28 jQuery
vue element ui validate 主动触发错误提示操作
2020/09/21 Javascript
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
[16:56]教你分分钟做大人:司夜刺客
2014/10/30 DOTA
django 使用全局搜索功能的实例详解
2019/07/18 Python
Python-jenkins 获取job构建信息方式
2020/05/12 Python
keras使用Sequence类调用大规模数据集进行训练的实现
2020/06/22 Python
html5 canvas里绘制椭圆并保持线条粗细均匀的技巧
2013/03/25 HTML / CSS
加拿大知名的国际儿童品牌:Hatley
2016/11/09 全球购物
IWOOT美国:新奇的小玩意
2018/04/27 全球购物
美国美食礼品篮网站:Gourmet Gift Baskets
2019/12/15 全球购物
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
会计与审计毕业生自荐信范文
2013/12/30 职场文书
追悼会主持词
2014/03/20 职场文书
个人剖析材料范文
2014/09/30 职场文书
2015年骨干教师工作总结
2015/05/26 职场文书
2019暑假阅读倡议书
2019/06/24 职场文书
解决Jupyter-notebook不弹出默认浏览器的问题
2021/03/30 Python
详解PyTorch模型保存与加载
2022/04/28 Python