多线程随机数生成重复问题

问题背景

在设备与服务器端定义的json类型的日志上报消息结构中,定义了字段msgId的字段作为唯一关键字,用于唯一标记单条上报消息。类似于手机的UUID。在测试过程中发现存在大量日志上报的时候,会出现实际本地产生日志条数,小于服务器端elastic-search服务器记录日志条数的现象,经分析是由于上传标记的唯一关键字中msgId重复,导致服务器端日志被顶掉的问题,特此记录。

流程介绍

1、处理流程

原有流程下,日志上报由一个独立的本地进程提供服务,避免阻塞主服务的执行流程,而要执行日志上报的需求在多个进程中存在,故而对服务进行了简单的封装,由独立的进程通过接收进程间通信的方式来提供服务。消息接收模块收到消息后,启动消息处理线程,对消息进行封装处理,并添加上必要的头部信息,加入到队列中,由发送线程从队列中取出消息,发送给服务器。

在这里插入图片描述

2、随机数生成流程

与服务器之间交互的msgId约定为一个32位的随机数。在本地对序列号,时间戳和随机数构成的内容进行md5计算。

    char szBuf[256] = {0};
    char szMd5Buf[33] = {0};
    snprintf(szBuf,sizeof(szBuf),"device%s-%lld-%u", srcId.c_str(),i64CurTime,XXX_Rand());
    compute_buf_md5(szBuf,strlen(szBuf),szMd5Buf,sizeof(szMd5Buf));

XXX_Rand函数为公司提供的函数封装,即调用srand函数,并以当前开机到现在的启动时间为种子。

问题分析

在开启了日志打印,对msgId的生成过程进行分析,发现如下结果。一般情况下,只会出现单条打印。

[INFO][Func:compute_msgId]: szBuf[deviceC15668877-2729789-1022948994] szMd5Buf[24fe2f01491e25a650bdf36873275dce] 

但在相当短的时间内同时接收到两个日志发送的请求时,会出现如下的打印。

[INFO][Func:compute_msgId]: szBuf[deviceC15668877-2989915-1831772470] szMd5Buf[40390fc054545f055e9603681a9e6cc5] 
[INFO][Func:compute_msgId]: szBuf[deviceC15668877-2989915-1831772470] szMd5Buf[40390fc054545f055e9603681a9e6cc5] 

可以看到时间戳与随机数是完全一样的。这个现象在双核设备中较为容易复现,在更低端的单核设备中,以同一套代码运行,基本不会出现。可以猜测在双核的情况下,因本地的消息处理线程几乎同时启动并进行消息处理。而这里作为srand函数的随机数的时间戳是毫秒级的时间戳,故而会出现了时间戳一致,同时随机数也一致的情况。

解决方案和结果

因这里是多线程并发时出现的问题,故而可以引入线程id作为要被MD5的源字符串的一部分。修改为如下结构

    snprintf(szBuf,sizeof(szBuf),"device%s-%lld-%u-%lu", srcId.c_str(),i64CurTime,XXX_Rand(), pthread_self());
    compute_buf_md5(szBuf,strlen(szBuf),szMd5Buf,sizeof(szMd5Buf));

重新进行测试,可以发现带上了线程id之后,即使出现3个线程并发,获取到随机数和时间戳一致的情况,也可以通过线程id进行区分,得到不同的计算md5之后的msgId。

[INFO][Func:compute_msgId]: szBuf[deviceC15668877-6292510-852175900-3059578048] szMd5Buf[659296d7263566a8cd89fda52c8e6204] 
[INFO][Func:compute_msgId]: szBuf[deviceC15668877-6292510-852175900-3062723776] szMd5Buf[c640484c8a4cdcaa03fcfa48348356b3] 
[INFO][Func:compute_msgId]: szBuf[deviceC15668877-6292510-852175900-3061675200] szMd5Buf[13a1a8af937dc4e99cd2c1d68e8d94f8] 

以上便是解决多线程使用时间戳作为种子生成随机数重复导致的问题的起因和解决流程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值