如何通过雪花算法用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学习笔记(二)基础语法
Jun 06 Python
9种python web 程序的部署方式小结
Jun 30 Python
Python标准库之Sys模块使用详解
May 23 Python
用Python的Flask框架结合MySQL写一个内存监控程序
Nov 07 Python
轻松掌握python设计模式之访问者模式
Nov 18 Python
Python 模拟员工信息数据库操作的实例
Oct 23 Python
Python3实现定时任务的四种方式
Jun 03 Python
python词云库wordcloud的使用方法与实例详解
Feb 17 Python
python安装dlib库报错问题及解决方法
Mar 16 Python
Python实现播放和录制声音的功能
Aug 12 Python
深入了解Python装饰器的高级用法
Aug 13 Python
python 图像增强算法实现详解
Jan 24 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中利用substr_replace将指定两位置之间的字符替换为*号
2011/01/27 PHP
教你如何开启shopnc b2b2c 伪静态
2014/10/21 PHP
为你的网站增加亮点的9款jQuery插件推荐
2011/05/03 Javascript
js字符串的各种格式的转换 ToString,Format
2011/08/08 Javascript
JS复制内容到剪切板的实例代码(兼容IE与火狐)
2013/11/19 Javascript
FireBug 调试JS入门教程 如何调试JS
2013/12/23 Javascript
Javascript类型转换的规则实例解析
2016/02/23 Javascript
JS实现Select的option上下移动的方法
2016/03/01 Javascript
javascript鼠标滑过显示二级菜单特效
2020/11/18 Javascript
jQuery中实现prop()函数控制多选框(全选,反选)
2016/08/19 Javascript
ionic组件ion-tabs选项卡切换效果实例
2016/08/27 Javascript
vue.js入门教程之绑定class和style样式
2016/09/02 Javascript
Angular-Touch库用法示例
2016/12/22 Javascript
微信小程序 地图map详解及简单实例
2017/01/10 Javascript
vue快捷键与基础指令详解
2017/06/01 Javascript
SeaJS中use函数用法实例分析
2017/10/10 Javascript
初识 Vue.js 中的 *.Vue文件
2017/11/22 Javascript
详解小程序如何避免多次点击,重复触发事件
2019/04/08 Javascript
vue+element实现打印页面功能
2019/05/20 Javascript
typescript nodejs 依赖注入实现方法代码详解
2019/07/21 NodeJs
2020淘宝618理想生活列车自动领喵币js脚本的代码
2020/06/02 Javascript
python网络编程实例简析
2014/09/26 Python
Python标准库06之子进程 (subprocess包) 详解
2016/12/07 Python
PyQt5每天必学之日历控件QCalendarWidget
2018/04/19 Python
Python在后台自动解压各种压缩文件的实现方法
2020/11/10 Python
Html5写一个简单的俄罗斯方块小游戏
2019/12/03 HTML / CSS
Bally澳大利亚官网:瑞士奢侈品牌
2018/11/01 全球购物
C#中有没有静态构造函数,如果有是做什么用的?
2016/06/04 面试题
保荐人的岗位职责
2013/11/19 职场文书
学生会主席就职演讲稿
2014/01/14 职场文书
难忘的一天教学反思
2014/04/30 职场文书
党员干部四风问题整改措施思想汇报
2014/10/12 职场文书
《卧薪尝胆》读后感3篇
2019/12/26 职场文书
Django实现在线无水印抖音视频下载(附源码及地址)
2021/05/06 Python
Java用自带的Image IO给图片添加水印
2021/06/15 Java/Android
使用CSS实现六边形的图片效果
2022/08/05 HTML / CSS