多線程隨機數生成重複問題

問題背景

在設備與服務器端定義的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] 

以上便是解決多線程使用時間戳作爲種子生成隨機數重複導致的問題的起因和解決流程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章