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相关推荐

  1. 雪花玻璃球(Snow Globe)

    雪花玻璃球 示例 HTML CSS JS 更多有趣示例 尽在知屋安砖社区 示例 HTML <div class="snow-globe"><div class=& ...

  2. D3D中的粒子系统(4)

    14.3具体的粒子系统:雪.火.粒子枪 现在让我们用cParticleSystem类开始一个具体的粒子系统,为了说明用意,这些系统的设计很简单,没有用到cParticleSystem类所提供的所有灵活 ...

  3. 基于snowfall的玫瑰花瓣飘落效果

    玫瑰花瓣飘落效果 做专题时,常常需要添加一些动效,可以让我们的页面活起来  就像最近某电商网站一系列雪花飘落效果  看了网上封装的snowfall.js配置挺方便的,用起来也蛮好的 用法 1.首先引入 ...

  4. jquery/zepto 圣诞节雪花飞扬

    下载地址: http://www.html5tricks.com/jquery-html5-christ-snow.html 演示地址: http://www.html5tricks.com/jque ...

  5. D3D粒子系统设计关键要点

    粒子系统设计思想 用D3D8以后用点精灵来指定一个粒子,而不是D3D8以前的需要用公告板平面(四个顶点)来模拟一个粒子. 点精灵粒子的大小,纹理颜色,都可以用渲染状态来改变.粒子系统的渲染信息结构(位 ...

  6. 【旅游】【转载】如何徒步虎跳峡

    徒步过虎跳峡的驴友已经太多太多了,一些中文洋文如"梯纳斯"."哈夫威"."28道拐"等名称常为很多走过或还没走的人所津津乐道,当然也还会有更 ...

  7. Mybatis-plus笔记整理

    导入依赖 <!--MP--> <dependency><groupId>com.baomidou</groupId><artifactId> ...

  8. op 圣诞节活动_假期的八个极好的圣诞节项目

    op 圣诞节活动 It's Christmas Eve and if you're lucky you've got some time off ahead of you. Let's put tha ...

  9. CSS3:有雪花的导航栏实例

    1.CSS3中带有渐变色背景色处理:(根据不同的) 参考链接:http://www.cnblogs.com/luckly-hf/archive/2011/11/14/2248149.html 2.带雪 ...

最新文章

  1. SAP QM 执行事务代码QE01为检验批录入结果直接进入Multiple Specification标签页?
  2. SQL语句之DWL、DCL语句
  3. WinError 145] 目录不是空的
  4. vs中如和根据项目生成类图_迁移WPF项目到.NET Core
  5. plesk 打不开php,Laravel在Plesk背后,遇到PHP版本困难
  6. 第三章:3.2  get 请求
  7. eclipse导出Maven依赖的Jar
  8. python怎么清空屏幕_python3.6怎么清屏幕
  9. 安装markdownPad+awesomium
  10. JS网页恶搞代码,不断弹出、关不掉的对话框
  11. Unity官方文档解读之如何使用粒子系统创建汽车尾气
  12. 7-1 大師と仙人との奇遇 (20 分)
  13. Referrer还是Referer? 一个迷人的错误
  14. 如何实现无线网卡上外网+有线上内网=同时上网
  15. ListView实现倒计时功能
  16. sqlmap tamper mysql_sqlmap之常用tamper脚本
  17. 计算机u盘被禁用怎么办,笔记本电脑U盘等USB设备被禁用怎么处理
  18. 【循序渐进学Python】Python中的循环(一)——for循环(嵌套)与range函数
  19. 进销存系统_用户信息更新密码修改(3)
  20. python之父是( )_Python之父加入微软,一开口就知道是老“凡学家”了

热门文章

  1. php基础复习函数、类、对象、设计模式....
  2. 10, excel vba 修改单元格的颜色
  3. 给Lulu的书签,链接及其他
  4. MTK平台LK中的APP_START(LK app service)介绍
  5. 图像去模糊——暗通道
  6. ucOS-II基于ARM920T的OSIntCtxSw实现分析
  7. ssm+java+vue基于微信小程序的新生自助报到系统#毕业设计
  8. 程序员团队名称和口号_第四季度团队口号励志标语大全
  9. 角速度求积分能得到欧拉角吗_数值计算方法 第六章 数值积分和数值微分
  10. 2022年API安全研究报告