如何通过雪花算法用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实现的重启关机程序实例
Aug 21 Python
基于并发服务器几种实现方法(总结)
Dec 29 Python
Python使用matplotlib模块绘制图像并设置标题与坐标轴等信息示例
May 04 Python
详解python单元测试框架unittest
Jul 02 Python
flask入门之表单的实现
Jul 18 Python
对python 读取线的shp文件实例详解
Dec 22 Python
浅谈Python3中strip()、lstrip()、rstrip()用法详解
Apr 29 Python
python 并发编程 非阻塞IO模型原理解析
Aug 20 Python
python BlockingScheduler定时任务及其他方式的实现
Sep 19 Python
Tensorflow 模型转换 .pb convert to .lite实例
Feb 12 Python
深入了解Python 方法之类方法 &amp; 静态方法
Aug 17 Python
Python开发入门——迭代的基本使用
Sep 03 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登录环节防止sql注入的方法浅析
2014/06/30 PHP
Yii2.0预定义的别名功能小结
2016/07/04 PHP
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
关于JS中的闭包浅谈
2013/08/23 Javascript
jquery mobile动态添加元素之后不能正确渲染解决方法说明
2014/03/05 Javascript
javascript面向对象程序设计(一)
2015/01/29 Javascript
Node.js 学习笔记之简介、安装及配置
2015/03/03 Javascript
JS实现表格数据各种搜索功能的方法
2015/03/03 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
jQuery简单倒计时效果完整示例
2016/09/20 Javascript
ES6新特征数字、数组、字符串
2016/10/01 Javascript
Javascript中内建函数reduce的应用详解
2016/10/20 Javascript
js仿新浪微博消息发布功能
2017/02/17 Javascript
基于BootStrap的文本编辑器组件Summernote
2017/10/27 Javascript
详解Angular-ui-BootStrap组件的解释以及使用
2018/07/13 Javascript
不得不知的ES6小技巧
2018/07/28 Javascript
WebGL three.js学习笔记之阴影与实现物体的动画效果
2019/04/25 Javascript
python学习笔记之列表(list)与元组(tuple)详解
2017/11/23 Python
python使用turtle库绘制时钟
2020/03/25 Python
python3利用tcp实现文件夹远程传输
2018/07/28 Python
Python基于SMTP协议实现发送邮件功能详解
2018/08/14 Python
Python3中内置类型bytes和str用法及byte和string之间各种编码转换 问题
2018/09/27 Python
Flask框架学习笔记之使用Flask实现表单开发详解
2019/08/12 Python
如何为Python终端提供持久性历史记录
2019/09/03 Python
浅析python 动态库m.so.1.0错误问题
2020/05/09 Python
使用Pycharm在运行过程中,查看每个变量的操作(show variables)
2020/06/08 Python
Python打印不合法的文件名
2020/07/31 Python
阿巴庭院:Abba Patio
2019/06/18 全球购物
彪马俄罗斯官网:PUMA俄罗斯
2019/07/13 全球购物
印度领先的眼镜电子商务网站:Lenskart
2019/12/16 全球购物
若通过ObjectOutputStream向一个文件中多次以追加方式写入object,为什么用ObjectInputStream读取这些object时会产生StreamCorruptedException?
2016/10/17 面试题
英文简历中的自我评价用语
2013/12/09 职场文书
微笑面对生活演讲稿
2014/09/23 职场文书
老龙头导游词
2015/02/11 职场文书
入党积极分子个人总结
2015/03/02 职场文书
2015年监理个人工作总结
2015/05/23 职场文书