一篇让你学会雪花算法
前言
大家好,篇让我是学会雪花盼盼!
以前用rand和srand生成过伪随机数,伪随机数的算法序列是固定的,今天学习生成真正的篇让随机数的生成。
熵池
利用/dev/urandom可以生成随机数的学会雪花值,/dev/urandomLinux下的算法熵池,所谓熵池就是篇让当前系统下的环境噪音,描述了一个系统的学会雪花混乱程度,环境噪音由这几个方面组成,算法如内存的篇让使用,文件的学会雪花使用量,不同类型的算法进程数量等等。
利用/dev/urandom可以生成随机数的篇让值,/dev/urandomLinux下的学会雪花熵池,所谓熵池就是算法当前系统下的环境噪音,描述了一个系统的企商汇混乱程度,环境噪音由这几个方面组成,如内存的使用,文件的使用量,不同类型的进程数量等等。
#include <stdio.h> #include <fcntl.h> int main() { int randNum = 0; int fd = 0; for(int i=0;i<5;i++) { fd = open("/dev/urandom", O_RDONLY); read(fd, (char *)&randNum, sizeof(int)); close(fd); printf("randNum is %dn", randNum); } return 0; }运行结果:
mapan@mapan-virtual-machine:~/c++$ ./a.out randNum is 94961710 randNum is -523780773 randNum is 1542169420 randNum is -1632410867每次打印的5个随机数都不一样,其实它的随机性也不太好。雪花算法生成的数的随机性很好,通常在分布式系统中生成唯一ID。
雪花算法
SnowFlake算法产生的ID是一个64位的整型,结构如下(每一部分用“-”符号分隔):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 00000000000
1位标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以为0;
41位时间戳部分,这个是毫秒级的站群服务器时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年;
10位节点部分,Twitter实现中使用前5位作为数据中心标识,后5位作为机器标识,可以部署1024个节点;
12位序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;
/* snowflake ID 生成策略 毫秒级时间41位+机器ID 10位+毫秒内序列12位。 0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+ 前41bits是以微秒为单位的timestamp。 接着10bits是事先配置好的机器ID。 最后12bits是累加计数器。 macheine id(10bits)标明最多只能有1024台机器同时产生ID,sequence number(12bits)也标明1台机器1ms中最多产生4096个ID, * 注意点,因为使用到位移运算,所以需要64位操作系统,不然生成的ID会有可能不正确 */ #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <sched.h> #include <linux/unistd.h> #include <sys/syscall.h> #include <errno.h> #include<linux/types.h> #include<time.h> #include <stdint.h> #include <sys/time.h> struct globle { int global_int:12; uint64_t last_stamp; int workid; int seqid; }; void set_workid(int workid); pid_t gettid( void ); uint64_t get_curr_ms(); uint64_t wait_next_ms(uint64_t lastStamp); int atomic_incr(int id); uint64_t get_unique_id(); #include "snowflake.h" struct globle g_info; #define sequenceMask (-1L ^ (-1L << 12L)) //L表示long型 4095 void set_workid(int workid) { g_info.workid = workid; } pid_t gettid( void )//获取线程ID { return syscall( __NR_gettid ); } uint64_t get_curr_ms() //获取毫秒 { struct timeval time_now; gettimeofday(&time_now,NULL); uint64_t ms_time =time_now.tv_sec*1000+time_now.tv_usec/1000; return ms_time; } uint64_t wait_next_ms(uint64_t lastStamp) { uint64_t cur = 0; do { cur = get_curr_ms(); } while (cur <= lastStamp); return cur; } int atomic_incr(int id)//累加 { __sync_add_and_fetch(&id, 1); return id; } uint64_t get_unique_id() { uint64_t uniqueId=0; uint64_t nowtime = get_curr_ms();//获取当前毫秒数 uniqueId = nowtime << 22; //填补时间戳部分 //0x3ff 1023,二进制对应11 1111 1111 //100的二进制0000 0000 0000 0000 0000 0000 0110 0100 //先执行移位 uniqueId |= (g_info.workid & 0x3ff) << 12; //填补节点部分 if (nowtime < g_info.last_stamp) { perror("error"); exit(-1); } if (nowtime == g_info.last_stamp) { //4095的二进制0000 1111 1111 1111 [long型] g_info.seqid = atomic_incr(g_info.seqid) & sequenceMask; if (g_info.seqid == 0) //seqid=0防止冲突,修改时间 { nowtime = wait_next_ms(g_info.last_stamp);//获取大于当前时间的免费源码下载time } } else { g_info.seqid = 0; } g_info.last_stamp = nowtime; uniqueId |= g_info.seqid;//填补序列号部分 return uniqueId; } int main() { set_workid(100); int i; for(i=0;i<10;i++) { uint64_t unquie = get_unique_id(); printf("pthread_id:%u, id [%llu]n",gettid(),unquie); } return; }运行结果:
mapan@mapan-virtual-machine:~/c++$ ./a.out pthread_id:4970, id [6595660141600063488] pthread_id:4970, id [6595660141600063489] pthread_id:4970, id [6595660141600063490] pthread_id:4970, id [6595660141600063491] pthread_id:4970, id [6595660141600063492]结尾
雪花算法很多大厂都在使用,随机性比熵池要好。雪花算法的思想在平时工作中也有用到,将多个数据拼到一个值里面是常用套路,要掌握。
相关文章
将电脑光驱改装为音响的教程(简单改装让电脑光驱释放出音响魅力,探索DIY的乐趣)
摘要:电脑光驱一直以来都是用来读取光盘的设备,但是你可知道,通过简单的改装,你也可以让电脑光驱变成一个小型音响呢?本篇文章将为你介绍以电脑光驱改装音响的教程,让你探索DIY的乐趣并享受优...2025-11-05
关键的关注点:大数据正在创造大量的隐私主题需要及时处理,宜早不宜晚。该报告的引文说到:”本报告一个显著的发现是大数据分析将个人信息用于供房、信贷、雇用、健康、教育和商场购物,有潜力使长期存在的公民权利2025-11-05
CDO正在成为炙手可热的明星职位,但根据IBM的调研,很多企业其实对CDO的概念还不甚明了。据IBM全球商业服务部的Glenn Finch介绍:两年半前我们注意到CDO职位的兴起,但企业对CDO岗位的2025-11-05
如何使用Percona Toolkit解决Mysql主从不同步问题
由于各种原因,mysql主从架构经常会出现数据不一致的情况出现,大致归结为如下几类1:备库写数据 2:执行non-deterministic query 3:回滚掺杂事务表2025-11-05- 摘要:随着时间的推移,电脑内部会积累大量灰尘,如果不及时清理,会导致电脑散热不良,影响性能甚至损坏硬件。掌握正确的DIY电脑清灰方法非常重要。本文将介绍一些简单易行的清灰技巧,帮助您保持...2025-11-05
很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间。这里共享一个脚本:CREATETABLE#tablespaceinfo ( nameinfoVARCHAR(50), rowsinfo2025-11-05


最新评论