snow flake
snow flake
分布式系统需要有一个方法去分配一个唯一的ID。如mysql 分表之后,如果各个表使用的都是自增ID 那么不同表之间的ID 就会重复,对于其他业务可能会认为是同一条数据,或者造成别的问题。所以需要一个分配ID的方法。
通常有两种方式
mysql
使用mysql 最为关节节点,每次分配数百个ID到内存,然后应用再在内存中取值。
这种方式较为复杂,并且依赖于分配器所在的DB,如果出了问题,所有的依赖的表都会挂掉。
使用 snowflake 算法分配
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
定义是如上定义。但是可以学习他的原理以及是如何做到唯一性。并且在分布式DB。如TIDB中,ID 是不允许设置自增的ID的。因为连续的ID会被插入到同一个TIKV 内,会造成热数据,需要数据的分散,而snowflake就很好的满足了这一点。
- mysql 分配ID 的方式还是比较集中的,任然会被分配到同一台TIKV 节点上面,不适合作为TIDB的ID。
- snowflake 的时间在中间41bit 上,能够很好的分散数据。所以作为TIDB的ID 非常合适。
设计
关键在如何标志唯一性的几个bit。
在没有别的方式获取机器ID,数据ID 的情况下。决定使用 ip + pid 的方式来标志。
原有的10bit分配其实还是有隐藏条件的。如果在单机中多个进程同时产生ID 还是会重复。多进程就不合适了
IP 使用数字表示需要 4Byte -> 32 bit
PID 到几k 上万都有可能。所以还是要做处理。
这里取IP 后16bit.(重复可能非常小)
PID mod 128 7bit
最后代码如下
#!/usr/bin/env python
# -*- coding: UTF-8 -*-import time
import os
from time_utils import get_timestamp
import socket
import threadingstart_time = int(time.mktime(time.strptime('2019-01-01 00:00:00', "%Y-%m-%d %H:%M:%S")))"""
ip -> 16
pid -> 7--------------------------------------------————
|sign | timestamp left| work node id| sequence |
---------------------------------------------
|1 bit| 30bit | 23bit | 10bit |
---------------------------------------------——snowFlake 三部分组成sign (1 bit) 为正数timestamp left (41 bit) s 相对于基础时间 的剩余时间:work node 16 bit ip 后16bit + pid mod % 128 7bit -> 23bit:sequence 一秒生成的ID 数量使用:
为每一个表实例化一个全局对象
snow = SnowFlake()"""def get_host_ip():"""查询本机ip地址:return: ip"""try:s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.connect(('8.8.8.8', 80))ip = s.getsockname()[0]finally:s.close()return ipdef get_work_id_ip_part():ip = get_host_ip()ip_list = ip.split('.')return (int(ip_list[2]) << 8) + int(ip[3])def get_work_id_pid_part():return os.getpid() % 128work_ip_id = get_work_id_ip_part()
work_pid_id = get_work_id_pid_part()class SnowFlake(object):# 各个部分所占位数 类变量sequence_bit = 10work_node_id_bit = 23time_stamp_left_bit = 30sign_bit = 1sequence_max_value = 1 << sequence_bitwork_node_id_max_value = 1 << work_node_id_bittime_stamp_left_max_value = 1 << time_stamp_left_bitwork_node_id_shift = sequence_bittime_stamp_left_shift = sequence_bit + work_node_id_bitdef __init__(self):self.start = start_timeself.last_timestamp = int(time.time())self.sequence = 0# self.sequence = self.sequence_max_value - 1self.work_id = (work_ip_id << 7) + work_pid_id# print 'work_id:%s' % self.work_idself.lock = threading.RLock()def get_id(self):with self.lock:now = get_timestamp()# 时间回退 异常if now < self.last_timestamp:raise Exception('SnowFlake now:%s small than last_timestamp:%s', now, self.last_timestamp)time_stamp_count = now - self.start# 同一秒内 sequence 累加, 否则清0if now == self.last_timestamp:self.sequence += 1else:self.sequence = 0self.last_timestamp = now# 已经累计到最大值 需要休眠1s 再次调用if self.sequence == self.sequence_max_value:time.sleep(1)return self.get_id()current_id = time_stamp_count << self.time_stamp_left_shift | \self.work_id << self.work_node_id_shift | self.sequencereturn current_idsnow = SnowFlake()
改进
后续发现使用jenkins 部署的时候可以获取项目名称以及实例的index。我们内部一个项目应该不超过8所以给3bit APP_NAME.
work_node_id app 3 bit worker id 7 bit 13 pid 8102 -> 23 bit
优化了中间的work_id。但是对于实例内多进程的话似乎没有找到特别好的办法,现在采用mod 8192 的方式。虽然概率低,但是还是存在分享。之前考虑在单机做一个分配器,但是这实在太过于麻烦了。。
snow flake相关推荐
- 雪花玻璃球(Snow Globe)
雪花玻璃球 示例 HTML CSS JS 更多有趣示例 尽在知屋安砖社区 示例 HTML <div class="snow-globe"><div class=& ...
- D3D中的粒子系统(4)
14.3具体的粒子系统:雪.火.粒子枪 现在让我们用cParticleSystem类开始一个具体的粒子系统,为了说明用意,这些系统的设计很简单,没有用到cParticleSystem类所提供的所有灵活 ...
- 基于snowfall的玫瑰花瓣飘落效果
玫瑰花瓣飘落效果 做专题时,常常需要添加一些动效,可以让我们的页面活起来 就像最近某电商网站一系列雪花飘落效果 看了网上封装的snowfall.js配置挺方便的,用起来也蛮好的 用法 1.首先引入 ...
- jquery/zepto 圣诞节雪花飞扬
下载地址: http://www.html5tricks.com/jquery-html5-christ-snow.html 演示地址: http://www.html5tricks.com/jque ...
- D3D粒子系统设计关键要点
粒子系统设计思想 用D3D8以后用点精灵来指定一个粒子,而不是D3D8以前的需要用公告板平面(四个顶点)来模拟一个粒子. 点精灵粒子的大小,纹理颜色,都可以用渲染状态来改变.粒子系统的渲染信息结构(位 ...
- 【旅游】【转载】如何徒步虎跳峡
徒步过虎跳峡的驴友已经太多太多了,一些中文洋文如"梯纳斯"."哈夫威"."28道拐"等名称常为很多走过或还没走的人所津津乐道,当然也还会有更 ...
- Mybatis-plus笔记整理
导入依赖 <!--MP--> <dependency><groupId>com.baomidou</groupId><artifactId> ...
- op 圣诞节活动_假期的八个极好的圣诞节项目
op 圣诞节活动 It's Christmas Eve and if you're lucky you've got some time off ahead of you. Let's put tha ...
- CSS3:有雪花的导航栏实例
1.CSS3中带有渐变色背景色处理:(根据不同的) 参考链接:http://www.cnblogs.com/luckly-hf/archive/2011/11/14/2248149.html 2.带雪 ...
最新文章
- SAP QM 执行事务代码QE01为检验批录入结果直接进入Multiple Specification标签页?
- SQL语句之DWL、DCL语句
- WinError 145] 目录不是空的
- vs中如和根据项目生成类图_迁移WPF项目到.NET Core
- plesk 打不开php,Laravel在Plesk背后,遇到PHP版本困难
- 第三章:3.2 get 请求
- eclipse导出Maven依赖的Jar
- python怎么清空屏幕_python3.6怎么清屏幕
- 安装markdownPad+awesomium
- JS网页恶搞代码,不断弹出、关不掉的对话框
- Unity官方文档解读之如何使用粒子系统创建汽车尾气
- 7-1 大師と仙人との奇遇 (20 分)
- Referrer还是Referer? 一个迷人的错误
- 如何实现无线网卡上外网+有线上内网=同时上网
- ListView实现倒计时功能
- sqlmap tamper mysql_sqlmap之常用tamper脚本
- 计算机u盘被禁用怎么办,笔记本电脑U盘等USB设备被禁用怎么处理
- 【循序渐进学Python】Python中的循环(一)——for循环(嵌套)与range函数
- 进销存系统_用户信息更新密码修改(3)
- python之父是( )_Python之父加入微软,一开口就知道是老“凡学家”了
热门文章
- php基础复习函数、类、对象、设计模式....
- 10, excel vba 修改单元格的颜色
- 给Lulu的书签,链接及其他
- MTK平台LK中的APP_START(LK app service)介绍
- 图像去模糊——暗通道
- ucOS-II基于ARM920T的OSIntCtxSw实现分析
- ssm+java+vue基于微信小程序的新生自助报到系统#毕业设计
- 程序员团队名称和口号_第四季度团队口号励志标语大全
- 角速度求积分能得到欧拉角吗_数值计算方法 第六章 数值积分和数值微分
- 2022年API安全研究报告