如何通过雪花算法用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刷投票的脚本实现代码
Nov 08 Python
Python多线程编程(六):可重入锁RLock
Apr 05 Python
利用Python的装饰器解决Bottle框架中用户验证问题
Apr 24 Python
Python文件右键找不到IDLE打开项解决办法
Jun 08 Python
Python实现通过解析域名获取ip地址的方法分析
May 17 Python
Python在OpenCV里实现极坐标变换功能
Sep 02 Python
Django项目创建到启动详解(最全最详细)
Sep 07 Python
Tensorflow 多线程与多进程数据加载实例
Feb 05 Python
python 解决tqdm模块不能单行显示的问题
Feb 19 Python
python redis存入字典序列化存储教程
Jul 16 Python
python调用有道智云API实现文件批量翻译
Oct 10 Python
如何创建一个Flask项目并进行简单配置
Nov 18 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输出金字塔的2种实现方法
2014/12/16 PHP
培养自己的php编码规范
2015/09/28 PHP
Laravel 5.4因特殊字段太长导致migrations报错的解决
2017/10/22 PHP
在b/s开发中经常用到的javaScript技术
2006/08/23 Javascript
jquery 事件对象属性小结
2010/04/27 Javascript
返回对象在当前级别中是第几个元素的实现代码
2011/01/20 Javascript
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
JSONP之我见
2015/03/24 Javascript
JavaScript实现自动弹出窗口并自动关闭窗口的方法
2015/08/06 Javascript
js中对函数设置默认参数值的3种方法
2015/10/23 Javascript
javascript实现右侧弹出“分享到”窗口效果
2016/02/01 Javascript
JavaScript中的操作符类型转换示例总结
2016/05/30 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
2016/06/09 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
angular使用bootstrap方法手动启动的实例代码
2017/07/18 Javascript
vue滚动轴插件better-scroll使用详解
2017/10/17 Javascript
解决jQuery使用append添加的元素事件无效的问题
2018/08/30 jQuery
详解Vue.js自定义tipOnce指令用法实例
2018/12/19 Javascript
layer.confirm()右边按钮实现href的例子
2019/09/27 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
2019/11/17 Javascript
JsonServer安装及启动过程图解
2020/02/28 Javascript
vue实现图片上传到后台
2020/06/29 Javascript
JSONObject与JSONArray使用方法解析
2020/09/28 Javascript
学习Python3 Dlib19.7进行人脸面部识别
2018/01/24 Python
pygame游戏之旅 python和pygame安装教程
2018/11/20 Python
python添加模块搜索路径和包的导入方法
2019/01/19 Python
使用django和vue进行数据交互的方法步骤
2019/11/11 Python
matplotlib绘制鼠标的十字光标的实现(内置方式)
2021/01/06 Python
如何使用css3实现一个类在线直播的队列动画的示例代码
2020/06/17 HTML / CSS
美特斯邦威官方商城:邦购网
2016/10/13 全球购物
马来西亚航空官方网站:Malaysia Airlines
2017/07/28 全球购物
送给他或她的礼物:FUN.com
2018/08/17 全球购物
傲盾软件面试题
2015/08/17 面试题
小学师德师风整改措施
2014/10/27 职场文书
实习工作表现评语
2014/12/31 职场文书