吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何使用雪花算法生成真正的隨機數

麥辣雞腿堡 ? 來源:盼盼編程 ? 作者:盼盼編程 ? 2023-10-09 10:05 ? 次閱讀

以前用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]
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7139

    瀏覽量

    89578
  • 算法
    +關注

    關注

    23

    文章

    4630

    瀏覽量

    93355
  • 序列
    +關注

    關注

    0

    文章

    70

    瀏覽量

    19599
收藏 人收藏

    評論

    相關推薦

    如何使用MSP430內部時鐘生成隨機數

    ■TI公司 MSP430微控制器產品部Lane Westlund不管是生成隨機器件地址、強化加密算法還是創建獨立產品密鑰,可靠地生成隨機數
    發表于 07-12 06:20

    Kintex上的真隨機數生成器測試失敗的原因有哪些?

    我想在Kintex-7上生成真正隨機數。我正在關注Xilinx發表的論文,其中環形振蕩器用于隨機數生成,LHCA已被用作擾碼器。但是,每當我捕獲11兆字節的數據(真
    發表于 04-26 11:06

    如何去實現真正地單片機隨機數

    最近需要用到單片機隨機數,但是用rand()產生的隨機數,發現每次單片機上電時產生的隨機數都是一樣的,沒有實現真正隨機數。查資料發現要用到
    發表于 12-02 07:11

    用rand形成的不是真正隨機數,怎么才能達到真正隨機?

    用rand形成的不是真正隨機數啊,,怎么才能達到真正隨機
    發表于 10-30 06:14

    神經網絡的偽隨機數生成方法

    為了克服有限精度效應對混沌系統的退化影響,改善所生成隨機序列的統計性能,設計了一種新的基于六維CNN(細胞神經網絡)的64 bit偽隨機數生成方法。在該方法中,通過控制六維CNN在每次
    發表于 02-02 15:49 ?0次下載

    隨機數生成算法

    在計算機上用數學的方法產生隨機數列是目前通用的方法,它的特點是占用的內存少,速度快.用數學方法產生的隨機數列是根據確定的算法推算出來的,嚴格說來并不是隨機的,因此一般稱用數學方法產生的
    發表于 04-03 10:25 ?6次下載

    C語言中隨機數生成代碼

    C語言中隨機數生成完整代碼:
    的頭像 發表于 02-20 09:21 ?1w次閱讀

    如何使用隨機數生成器來生成私鑰

    是偽隨機數生成器,它們都是由確定的算法,通過一個“種子”(比如“時間”),來產生“看起來隨機”的結果。
    發表于 03-18 10:40 ?5115次閱讀
    如何使用<b class='flag-5'>隨機數</b><b class='flag-5'>生成</b>器來<b class='flag-5'>生成</b>私鑰

    星系共識的隨機數生成算法對共識協議的作用

    基于PoW共識的區塊鏈系統由于挖礦的隨機性,以天然的方式為系統引入了熵,然而對于PoS和DPoS共識的區塊鏈系統,就需要單獨設計一種方式去引入熵,那就是隨機數生成算法??梢哉f隨機數
    發表于 05-06 13:47 ?915次閱讀

    如何利用SystemVerilog仿真生成隨機數

    采用SystemVerilog進行仿真則更容易生成隨機數,而且對隨機數具有更強的可控性。對于隨機變量,在SystemVerilog中可通過rand或randc加數據類型的方式定義。ra
    的頭像 發表于 10-30 10:33 ?1.1w次閱讀
    如何利用SystemVerilog仿真<b class='flag-5'>生成</b><b class='flag-5'>隨機數</b>

    單片機STM32F1隨機數生成探索與實踐(基于CUBEMX和KEIL5)

    隨機數廣泛地用于游戲、以及測試環境中,本文產生的隨機數將用于測試排序算法性能。一些高端型號的單片機具有硬件的隨機數發生器,如STM32F4,STM32H7等,從這些單片機的
    發表于 12-31 19:12 ?12次下載
    單片機STM32F1<b class='flag-5'>隨機數</b><b class='flag-5'>生成</b>探索與實踐(基于CUBEMX和KEIL5)

    用于生成隨機數的電子骰子

    電子發燒友網站提供《用于生成隨機數的電子骰子.zip》資料免費下載
    發表于 07-06 10:58 ?4次下載
    用于<b class='flag-5'>生成</b><b class='flag-5'>隨機數</b>的電子骰子

    Arduino Lotto隨機數生成

    電子發燒友網站提供《Arduino Lotto隨機數生成器.zip》資料免費下載
    發表于 11-02 10:59 ?0次下載
    Arduino Lotto<b class='flag-5'>隨機數</b><b class='flag-5'>生成</b>器

    隨機數生成器開源分享

    電子發燒友網站提供《隨機數生成器開源分享.zip》資料免費下載
    發表于 11-11 11:57 ?0次下載
    <b class='flag-5'>隨機數</b><b class='flag-5'>生成</b>器開源分享

    技術分享 | 隨機數生成過慢導致系統阻塞怎么辦?

    原理linux上隨機數生成原理是將系統的中斷信息收集起來放入熵池中,通過算法生成更多無序的數據,有了大量的無序數據之后,每次獲取隨機數,就
    的頭像 發表于 08-15 09:20 ?2467次閱讀
    技術分享 | <b class='flag-5'>隨機數</b><b class='flag-5'>生成</b>過慢導致系統阻塞怎么辦?
    百家乐销售视频| 大世界娱乐城真人娱乐| 百家乐官网网络赌博真假| 澳门百家乐赌| 百家乐官网开户送百元| 百家乐赢退输进有哪些| 百家乐官网扑克桌布| 百家乐翻天电影| 网上有百家乐官网玩吗| 百家乐揽子打法| 大发888扑克下载| 威斯汀百家乐官网的玩法技巧和规则 | 大发888娱乐城下载lm0| 机器百家乐官网心得| 大发888是什么游戏| 太阳百家乐官网网| 澳门永利| 澳门百家乐小游戏| 百家乐官网公式球打法| 百家乐倍投软件| 百家乐官网在线怎么玩| 庞博百家乐的玩法技巧和规则| 百家乐官网画哪个路单| 韦德娱乐| 百家乐博娱乐网赌百家乐的玩法技巧和规则| 沙龙百家乐官网怎申请| 大发888娱乐城下载lm0| 金冠百家乐娱乐城| 尖扎县| 澳门百家乐765118118| 杨公24山择日| 凤凰百家乐官网娱乐城| 大发888游戏平台403| 广州百家乐酒店用品制造有限公司 | 百家乐庄闲必赢| 临汾玩百家乐官网的人在那里找| 大发888有手机版本吗| 百家乐视频无法显示| 百家乐官网筹码盒| 利记娱乐| 大发888娱乐官网|