一些業務場景,比如說短信、push需要帶上跳轉鏈接,這個時候就需要把長鏈轉換為短鏈
長鏈如何轉短鏈?其實長鏈和生成短鏈的過程是沒有任何關系的,唯一的聯系就是生成以后做關聯
1:短鏈生成
結合實際工作中以及網上,大概兩種比較常規的方式,默認生成六位短鏈
方式一:通過移位+簡單的算法生成一個隨機數
第一步:做位移,並加上一個0,1隨機數
for (int i = 0; i < 36; i++) { int random = random.nextInt(2); randomNumber = random + (randomNumber << 1); }
加上0,1隨機數,是為了防止碰撞,這樣碰撞的幾率就差不多是1/2的36次方,屬於接收范圍
至於為什么循環36次,后面會說;至此,一個隨機數randomNumber已經生成
第二步:用隨機數映射到6位的短鏈
for (int i = 0; i < 6; i++) { charList.append(char62[(int) (k & randomNumber )]);
randomNum = (randomNum >> 6);
}
K是什么?K是63,16進制0x3F,和randomNumber做操作,得到一個62進制的數,然后取出來對應的那一位
62進制數組成:26位大寫字母+26位小寫字母+10個數字
然后randomNum右移6位,這就和上面的36次循環生成隨機數對應了
36次循環分成6份,每份隨機出來的0,1組合對應一個符號
方式二:信號發射器
這種方式借助於數據庫的自增主鍵id,然后把ID映射為62進制數的6位,這篇文章介紹
https://blog.csdn.net/xlgen157387/article/details/80026452
這種方式,要考慮分布式生成的情況,還有數據壓力。個人想法可以參考美團的leaf生成器,分段拿
到這里,已經生成了短鏈,但是短鏈和長鏈如何映射?
2:長鏈和短鏈的映射
對應關系肯定是要持久化到數據庫的,但是一旦並發量大的時候,數據庫壓力比較大,就需要考慮用緩存了;優先使用redis的時候,又沒法把全部的映射關系存起來,
覺得底層還是需要依賴分表來解決部分問題,用長鏈的md5和短鏈分表,分別做唯一鍵。這里唯一鍵的作用就是防止短鏈碰撞,在短鏈碰撞的時候可以進行重試。
還有就是長鏈和短鏈的映射關系我們在緩存的時候,可以認為是符合最近使用的原則,也就是我們只保留“熱點”的長鏈和短鏈在緩存的映射關系,這樣可以大大減少緩存的大小