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

    文章

    7026

    浏览量

    89034
  • 算法
    +关注

    关注

    23

    文章

    4612

    浏览量

    92888
  • 序列
    +关注

    关注

    0

    文章

    70

    浏览量

    19557
收藏 人收藏

    评论

    相关推荐

    如何使用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 5077次阅读
    如何使用<b class='flag-5'>随机数</b><b class='flag-5'>生成</b>器来<b class='flag-5'>生成</b>私钥

    星系共识的随机数生成算法对共识协议的作用

    基于PoW共识的区块链系统由于挖矿的随机性,以天然的方式为系统引入了熵,然而对于PoS和DPoS共识的区块链系统,就需要单独设计一种方式去引入熵,那就是随机数生成算法。可以说随机数
    发表于 05-06 13:47 897次阅读

    如何利用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 2323次阅读
    技术分享 | <b class='flag-5'>随机数</b><b class='flag-5'>生成</b>过慢导致系统阻塞怎么办?