自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇讓你學(xué)會(huì)雪花算法

開(kāi)發(fā) 前端 算法
以前用rand和srand生成過(guò)偽隨機(jī)數(shù),偽隨機(jī)數(shù)的序列是固定的,今天學(xué)習(xí)生成真正的隨機(jī)數(shù)的生成。

 [[419666]]

前言

大家好,我是盼盼!

以前用rand和srand生成過(guò)偽隨機(jī)數(shù),偽隨機(jī)數(shù)的序列是固定的,今天學(xué)習(xí)生成真正的隨機(jī)數(shù)的生成。

熵池

利用/dev/urandom可以生成隨機(jī)數(shù)的值,/dev/urandomLinux下的熵池,所謂熵池就是當(dāng)前系統(tǒng)下的環(huán)境噪音,描述了一個(gè)系統(tǒng)的混亂程度,環(huán)境噪音由這幾個(gè)方面組成,如內(nèi)存的使用,文件的使用量,不同類(lèi)型的進(jìn)程數(shù)量等等。

利用/dev/urandom可以生成隨機(jī)數(shù)的值,/dev/urandomLinux下的熵池,所謂熵池就是當(dāng)前系統(tǒng)下的環(huán)境噪音,描述了一個(gè)系統(tǒng)的混亂程度,環(huán)境噪音由這幾個(gè)方面組成,如內(nèi)存的使用,文件的使用量,不同類(lèi)型的進(jìn)程數(shù)量等等。

  1. #include <stdio.h> 
  2. #include <fcntl.h> 
  3.  
  4. int main() 
  5.         int randNum = 0; 
  6.         int fd = 0; 
  7.  
  8.     for(int i=0;i<5;i++) 
  9.     {       
  10.       fd = open("/dev/urandom", O_RDONLY);   
  11.       read(fd, (char *)&randNum, sizeof(int)); 
  12.       close(fd);  
  13.       printf("randNum is %d\n", randNum); 
  14.     } 
  15.  
  16.         return 0; 

運(yùn)行結(jié)果:

  1. mapan@mapan-virtual-machine:~/c++$ ./a.out  
  2. randNum is 94961710 
  3. randNum is -523780773 
  4. randNum is 1542169420 
  5. randNum is -1632410867 

每次打印的5個(gè)隨機(jī)數(shù)都不一樣,其實(shí)它的隨機(jī)性也不太好。雪花算法生成的數(shù)的隨機(jī)性很好,通常在分布式系統(tǒng)中生成唯一ID。

雪花算法

SnowFlake算法產(chǎn)生的ID是一個(gè)64位的整型,結(jié)構(gòu)如下(每一部分用“-”符號(hào)分隔):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 00000000000

1位標(biāo)識(shí)部分,在java中由于long的最高位是符號(hào)位,正數(shù)是0,負(fù)數(shù)是1,一般生成的ID為正數(shù),所以為0;

41位時(shí)間戳部分,這個(gè)是毫秒級(jí)的時(shí)間,一般實(shí)現(xiàn)上不會(huì)存儲(chǔ)當(dāng)前的時(shí)間戳,而是時(shí)間戳的差值(當(dāng)前時(shí)間-固定的開(kāi)始時(shí)間),這樣可以使產(chǎn)生的ID從更小值開(kāi)始;41位的時(shí)間戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年;

10位節(jié)點(diǎn)部分,Twitter實(shí)現(xiàn)中使用前5位作為數(shù)據(jù)中心標(biāo)識(shí),后5位作為機(jī)器標(biāo)識(shí),可以部署1024個(gè)節(jié)點(diǎn);

12位序列號(hào)部分,支持同一毫秒內(nèi)同一個(gè)節(jié)點(diǎn)可以生成4096個(gè)ID;

  1. /*  
  2.     snowflake  
  3.  
  4.     ID 生成策略  
  5.     毫秒級(jí)時(shí)間41位+機(jī)器ID 10位+毫秒內(nèi)序列12位。 
  6.     0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+  
  7.     前41bits是以微秒為單位的timestamp。 
  8.     接著10bits是事先配置好的機(jī)器ID。 
  9.     最后12bits是累加計(jì)數(shù)器。 
  10.     macheine id(10bits)標(biāo)明最多只能有1024臺(tái)機(jī)器同時(shí)產(chǎn)生ID,sequence number(12bits)也標(biāo)明1臺(tái)機(jī)器1ms中最多產(chǎn)生4096個(gè)ID, *  
  11.       注意點(diǎn),因?yàn)槭褂玫轿灰七\(yùn)算,所以需要64位操作系統(tǒng),不然生成的ID會(huì)有可能不正確  
  12. */   
  13.  
  14. #include <stdio.h>   
  15. #include <pthread.h>   
  16. #include <unistd.h>   
  17. #include <stdlib.h>   
  18. #include <sched.h>   
  19. #include <linux/unistd.h>   
  20. #include <sys/syscall.h>   
  21. #include <errno.h>   
  22. #include<linux/types.h>   
  23. #include<time.h>   
  24. #include <stdint.h>   
  25. #include <sys/time.h>   
  26.  
  27. struct  globle   
  28. {   
  29.     int global_int:12;   
  30.     uint64_t last_stamp;   
  31.     int workid;   
  32.     int seqid;   
  33. };   
  34.  
  35. void set_workid(int workid);   
  36. pid_t gettid( void );   
  37. uint64_t get_curr_ms();   
  38. uint64_t wait_next_ms(uint64_t lastStamp);   
  39. int atomic_incr(int id);   
  40. uint64_t get_unique_id(); 
  1. #include "snowflake.h" 
  2.  
  3. struct globle g_info; 
  4.  
  5. #define   sequenceMask  (-1L ^ (-1L << 12L))  //L表示long型     4095 
  6.  
  7. void set_workid(int workid) 
  8.  g_info.workid = workid; 
  9.  
  10. pid_t gettid( void )//獲取線程ID 
  11.   return syscall( __NR_gettid ); 
  12.  
  13. uint64_t get_curr_ms()  //獲取毫秒 
  14.   struct timeval time_now; 
  15.   gettimeofday(&time_now,NULL); 
  16.   uint64_t ms_time =time_now.tv_sec*1000+time_now.tv_usec/1000; 
  17.   return ms_time; 
  18.  
  19. uint64_t wait_next_ms(uint64_t lastStamp) 
  20.   uint64_t cur = 0; 
  21.   do { 
  22.     cur = get_curr_ms(); 
  23.   } while (cur <= lastStamp); 
  24.   return cur; 
  25.  
  26. int atomic_incr(int id)//累加 
  27.   __sync_add_and_fetch(&id, 1); 
  28.   return id; 
  29.  
  30. uint64_t get_unique_id() 
  31.   uint64_t  uniqueId=0; 
  32.   uint64_t nowtime = get_curr_ms();//獲取當(dāng)前毫秒數(shù) 
  33.  
  34.   uniqueId = nowtime << 22;   //填補(bǔ)時(shí)間戳部分 
  35.  
  36.   //0x3ff 1023,二進(jìn)制對(duì)應(yīng)11 1111 1111  
  37.   //100的二進(jìn)制0000 0000 0000 0000 0000 0000 0110 0100 
  38.   //先執(zhí)行移位 
  39.   uniqueId |= (g_info.workid & 0x3ff) << 12;   //填補(bǔ)節(jié)點(diǎn)部分 
  40.  
  41.   if (nowtime < g_info.last_stamp) 
  42.   { 
  43.     perror("error"); 
  44.     exit(-1); 
  45.   } 
  46.  
  47.   if (nowtime == g_info.last_stamp) 
  48.   { 
  49.     //4095的二進(jìn)制0000 1111 1111 1111      [long型] 
  50.     g_info.seqid = atomic_incr(g_info.seqid) & sequenceMask; 
  51.     if (g_info.seqid == 0)  //seqid=0防止沖突,修改時(shí)間 
  52.     { 
  53.       nowtime = wait_next_ms(g_info.last_stamp);//獲取大于當(dāng)前時(shí)間的time 
  54.     } 
  55.   } 
  56.   else 
  57.   { 
  58.     g_info.seqid  = 0; 
  59.   } 
  60.   g_info.last_stamp = nowtime; 
  61.  
  62.   uniqueId |= g_info.seqid;//填補(bǔ)序列號(hào)部分 
  63.   return uniqueId; 
  64.  
  65. int main() 
  66.   set_workid(100); 
  67.   int i; 
  68.   for(i=0;i<10;i++) 
  69.   { 
  70.     uint64_t unquie = get_unique_id(); 
  71.     printf("pthread_id:%u, id [%llu]\n",gettid(),unquie); 
  72.   } 
  73.  
  74.   return;   

運(yùn)行結(jié)果:

  1. mapan@mapan-virtual-machine:~/c++$ ./a.out  
  2. pthread_id:4970, id [6595660141600063488] 
  3. pthread_id:4970, id [6595660141600063489] 
  4. pthread_id:4970, id [6595660141600063490] 
  5. pthread_id:4970, id [6595660141600063491] 
  6. pthread_id:4970, id [6595660141600063492] 

結(jié)尾

雪花算法很多大廠都在使用,隨機(jī)性比熵池要好。雪花算法的思想在平時(shí)工作中也有用到,將多個(gè)數(shù)據(jù)拼到一個(gè)值里面是常用套路,要掌握。

責(zé)任編輯:武曉燕 來(lái)源: 盼盼編程
相關(guān)推薦

2021-09-14 07:26:26

組合問(wèn)題循環(huán)

2022-08-29 08:00:11

哈希表數(shù)組存儲(chǔ)桶

2022-02-11 08:45:28

通信協(xié)議CAN

2022-03-04 21:06:46

spring事務(wù)失效

2022-03-04 08:17:53

PageRank網(wǎng)絡(luò)等級(jí)

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2024-04-12 09:01:08

2022-06-04 07:46:41

HeapJVM

2023-01-03 08:31:54

Spring讀取器配置

2021-05-11 08:54:59

建造者模式設(shè)計(jì)

2021-07-05 22:11:38

MySQL體系架構(gòu)

2021-07-06 08:59:18

抽象工廠模式

2022-08-26 09:29:01

Kubernetes策略Master

2023-11-28 08:29:31

Rust內(nèi)存布局

2021-07-02 09:45:29

MySQL InnoDB數(shù)據(jù)

2022-08-23 08:00:59

磁盤(pán)性能網(wǎng)絡(luò)

2021-10-27 09:59:35

存儲(chǔ)

2021-07-02 08:51:29

源碼參數(shù)Thread

2021-07-16 22:43:10

Go并發(fā)Golang
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)