介紹一下snowflake和rc4
snowflake
是twitter公司開源的生成唯一ID的網路服務,具有很強的伸縮性,這裡只取用生成唯一ID的演算法部分。
rc4
(Rivest Cipher 4)是一種流加密演算法,金鑰長度可變,它的加解密使用相同的金鑰,因此也屬於對稱加密演算法。
為啥要介紹這兩種演算法?
其一, snowflake
可以生成唯一ID,而相比與 UUID
, snowflake
生成的ID更加“好用”,這個放在後面解釋。
其二, UUID
和 snowflake
雖然可以生成唯一ID,但是無法適用於所有場景,譬如說“生成推廣碼”。生成推廣碼的時候,希望儘可能短而精,很明顯唯一ID都不太短。
snowflake
snowflake的唯一ID是一個64bit的int型資料,相較於UUID來說耗費空間更小,可以更方便的作為資料庫主鍵來索引和排序。
生成過程:
- 置0不用
- timestamp(41bits)精確到ms。
- machine-id(10bits)該部分其實由datacenterId和workerId兩部分組成,這兩部分是在配置檔案中指明的。datacenterId(5bits)方便搭建多個生成uid的service,並保證uid不重複。workerId(5bits)是實際server機器的代號,最大到32,同一個datacenter下的workerId是不能重複的。
- sequence-id(12bits),該id可以表示4096個數字,它是在time相同的情況下,遞增該值直到為0,即一個迴圈結束,此時便只能等到下一個ms到來,一般情況下4096/ms的請求是不太可能出現的,所以足夠使用了。
優勢和缺陷:
- 速度快,無依賴,原理和實現簡單,也可以根據自己的需求做演算法調整
- 依賴機器時間,如果時間回撥可能導致重複的ID
rc4
RC4加密演算法也是一種基於金鑰流的加密演算法。
首先,rc4根據明文和金鑰生成的金鑰流,其長度和明文的長度是相等的,也就是說明文的長度是500位元組,那麼金鑰流也是500位元組,這也是我們用來生成 推廣碼
的原因之一了;其次,rc4是是對稱加密完全可以通過密文得到明文,也就是說在生成碼的時候把必要資訊放在明文中,在使用密文的時候可以不用查庫也能得到相關的資訊,譬如使用者ID,這是原因之二。
使用場景
現在需要生成一種碼,短小易記,且唯一,但並不需要大量。
上述的snowflake和UUID都很容易實現唯一,但是短小就不符合要求了。因為並不需要大量生成這種碼,因此我們考慮用 自增ID + RC4
來實現:
package main import ( "crypto/rc4" "encoding/hex" "fmt" "log" ) func main() { cipher, err := rc4.NewCipher([]byte("thisiskey")) if err != nil { log.Fatalf("wrong with NewCipher: %v", err) } c := map[string]bool{} for i := 0; i < 1000; i++ { src := []byte(fmt.Sprintf("%7d", i)) dst := make([]byte, len(src)) cipher.XORKeyStream(dst, src) s := toString(dst) // 密文是不可讀的位元組流,這裡採用hex編碼 println(s)// 形如:a09def6b6e4797 c[s] = true } println(len(c)) # 1000 } func toString(src []byte) string { return hex.EncodeToString(src) }