如何通过雪花算法用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 19 Python
Python入门之三角函数tan()函数实例详解
Nov 08 Python
在python中pandas的series合并方法
Nov 12 Python
在python中使用requests 模拟浏览器发送请求数据的方法
Dec 26 Python
Python HTML解析器BeautifulSoup用法实例详解【爬虫解析器】
Apr 05 Python
python读取图片的方式,以及将图片以三维数组的形式输出方法
Jul 03 Python
python解析yaml文件过程详解
Aug 30 Python
使用tensorflow实现矩阵分解方式
Feb 07 Python
Python读取文件内容为字符串的方法(多种方法详解)
Mar 04 Python
Python局部变量与全局变量区别原理解析
Jul 14 Python
使用Django的JsonResponse返回数据的实现
Jan 15 Python
使用Python获取字典键对应值的方法
Apr 26 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
第一个无线电台是由谁发明的
2021/03/01 无线电
第十四节 命名空间 [14]
2006/10/09 PHP
thinkPHP学习笔记之安装配置篇
2015/03/05 PHP
php判断数组中是否存在指定键(key)的方法
2015/03/17 PHP
php通过exif_read_data函数获取图片的exif信息
2015/05/21 PHP
PHP实现的Redis多库选择功能单例类
2017/07/27 PHP
CL vs ForZe BO5 第三场 2.13
2021/03/10 DOTA
JavaScript格式化数字的函数代码
2010/11/30 Javascript
jQuery实现的网页竖向菜单效果代码
2015/08/26 Javascript
全面解析Bootstrap中Carousel轮播的使用方法
2016/06/13 Javascript
详解webpack进阶之插件篇
2017/07/06 Javascript
node实现的爬虫功能示例
2018/05/04 Javascript
JavaScript高级函数应用之分时函数实例分析
2018/08/03 Javascript
微信小程序中如何计算距离某个节日还有多少天
2019/07/15 Javascript
Vue 动态路由的实现及 Springsecurity 按钮级别的权限控制
2019/09/05 Javascript
ES6中的Javascript解构的实现
2020/10/30 Javascript
Python编写的com组件发生R6034错误的原因与解决办法
2013/04/01 Python
用Python绘制漫步图实例讲解
2020/02/26 Python
python生成大写32位uuid代码
2020/03/03 Python
python else语句在循环中的运用详解
2020/07/06 Python
python中slice参数过长的处理方法及实例
2020/12/15 Python
python3.9.1环境安装的方法(图文)
2021/02/02 Python
CSS实现雨滴动画效果的实例代码
2019/10/08 HTML / CSS
HTML5声音录制/播放功能的实现代码
2018/05/03 HTML / CSS
Dune London官网:英国著名奢华鞋履品牌
2017/11/30 全球购物
介绍下Java中==和equals的区别
2013/09/01 面试题
玩具公司的创业计划书
2013/12/31 职场文书
继电保护工岗位职责
2014/01/05 职场文书
领导党性分析材料
2014/02/15 职场文书
乡镇办公室工作决心书
2014/03/11 职场文书
水电维修专业推荐信
2014/09/06 职场文书
违反交通法规检讨书
2014/09/10 职场文书
忠诚与背叛观后感
2015/06/04 职场文书
css3实现背景图片颜色修改的多种方式
2021/04/13 HTML / CSS
TensorFlow中tf.batch_matmul()的用法
2021/06/02 Python
星际争霸 Light vs Action 一场把教主看到鬼畜的比赛
2022/04/01 星际争霸