如何生成全局唯一标识
引出
大家都用過QQ或者微信吧, 當我們注冊的時候, 會被自動分配一個QQ號, 這個號碼是全局唯一且固定的, 那么, 如果是你來寫的話, 如何為新注冊的用戶分配一個號碼呢? 亦或是一個電商網站, 要為每個訂單生成一個訂單號? 再或是一個即時聊天, 要為每個消息生成一個消息ID?? 我簡單想了想
方案一
其實這事說簡單點, 不就是要為每個用戶都配一個數字么? 而且這個數字必須是之前沒有用過的. 那簡單了, 數數就完了唄, 123456往下數, 來一個發一個記一個.
如何實現? MySQL主鍵自增, 或者redis記一個key, 每次incr自增. 什么? QQ號從1開始太丑了? 簡單, 自增設置一個起始ID.
完美, 實現方案簡單粗暴, 而且不會出現重復.
方案二
使用時間戳. 使用當前時間戳來生成, 比如: 1585390459 這樣的數字. 但是時間戳是以秒為單位的, 如果一秒發生了多次請求, 那不就重復了么? 我想了想, 有一個簡單到爆的處理方法, 在后面再拼上0000-9999的隨機數, 這樣每秒有一萬個不重復的, 重復的概率就降低了, 在生成后還需要查詢是否已經存在, 若存在則重復生成.
方案三
說起來, 要生成這樣的隨機ID, 總要有一個地方來記錄已生成的進度, 如果完全隨機生成的話, 就不可避免的需要回查是否存在. 記錄生成進度的可以有很多: redis、MySQL等等. 或者可以存在一個發號器, 所有的ID都有它來生成, 不停的生成, 供其他請求分配使用, 就是一個生產者消費者.
小結
通過想了幾種方案, 發現了一些規律.
要想生成隨機ID, 首先, 要有一個不是隨機的而又是當前唯一持有的. 在這個前提下, 再各種添油加醋, 生成最終的ID. 就算你要調用隨機函數, 也得設置一個隨機種子不是? 莫非這就是傳說中的以不變應萬變…
很好, 那么現在問題就歸結為, 如何給每個用戶都配一個唯一標識
1.數數
直接想到的方案, 從1開始, 慢慢往后數, 而這個過程可以借助MySQL的主鍵自增, 也可以借助redis的單線程優勢. 等等吧,
2.用戶特征
可以根據不同用戶的特征, 如用戶的地域、性別、生辰等等, 來生成每個人的唯一標識, 此舉可以參考身份證號碼的生成, 每個人都是不一樣的
3.當前機器特征
找到執行代碼時的特定特征, 如: mac地址、時間戳、機器編號、線程ID等等
4.代碼運行次數
線程共享變量, 每次執行則+1.
等等等等
簡單想下來, 其實重要的是找到其中每次生成都和別人不一樣的那個點, 然后拿來稍作加工即可. 有點找不同的趕腳. 對了, 在網上看到了twitter的雪花算法, 基本也是找不同的思路. 關鍵就在于你是否能從各種功能繁雜的信息中找到那個不同的點. 如果實在找不到不同, 就只能人為的賦予他們不同了(自增ID等).
現在已經有很多工具了, uuid, MongoDB的objectid等, 基本可以拿來直接使用.
總結
以上是生活随笔為你收集整理的如何生成全局唯一标识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php取消转译代码,PHP在我不需要的时
- 下一篇: gff3转mysql_科学网-把GFF3