如何使用CL實現snowflake

TL;DR;

這是一篇為了完成寫作KPI而寫的博客,總結起來就是提供了一種用Common Lisp實現來自于Twitter的雪花算法的實現方案。成品在這里,本文只是簡單地描述一下生成雪花ID的大致思路,詳細內容請各位移步代碼倉庫查看。

上述代碼倉庫中的snowflake算法——如果我的實現確實可以稱作snowflake算法的話——的思路來自于下列兩個地方:

  1. http://www.lanindex.com/twitter-snowflake,64位自增id算法詳解/
  2. https://github.com/sony/sonyflake

如何獲取時間戳

Common Lisp本身提供了一個獲取時間戳的函數,也就是get-universal-time,可惜的是,這個函數所返回的并不是通常意義上的Epoch時間戳,而是自己的一套計算時間的方式中的表示時間的整數。為了獲得UNIX時間戳,需要借助于第三方庫local-time。為了可以獲取到毫秒精度的時間戳,一個可運行的函數如下

(defun now ()
  "Returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC."
  (let* ((now (local-time:now))
         (seconds (local-time:timestamp-to-unix now))
         (milliseconds (local-time:timestamp-millisecond now)))
    (+ (* 1000 seconds) milliseconds)))

如何獲取機器ID

這里參考了Sony的雪花ID算法中的思路,基于機器的內網IP地址來生成機器ID。當然了,Common Lisp標準中是沒有提供獲取機器的內網IP地址的方法的,這一點也可以借助于第三方庫實現,選用的是ip-interfaces。通過這個庫提供的get-ip-interfaces函數可以獲取到機器的所有“接口”,遍歷這個接口的列表后即可找出其中的內網IP。一臺機器可能會有多個內網IP,我的方法是選用了第一個找到的內網IP地址。當然了,還需要一個將向量轉化為數值的函數,并取出轉化為數值后的IP地址的低10位,作為機器ID。

序號

如果希望生成的ID是保持遞增的,那么就需要維護一個可以原子遞增的數值計數器。在真實的使用中可以通過Redis的INCR指令來生成這一個ID,但是因為這里的雪花ID算法是作為一個獨立的庫實現的,不需要依賴于數據庫等外部組建,因此這里就直接使用了Common Lisp自帶的random函數來生成這個序號了。

全文完

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,947評論 18 139
  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據使用者...
    保川閱讀 5,987評論 1 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,337評論 25 708
  • 3.4 說說相等和內部表示 在Lisp中主要有5種相等斷言,因為不是所有的對象被創建的時候都是相等意義上的相等。數...
    geoeee閱讀 1,867評論 0 6
  • 很久沒有寫下點東西,不是不想寫,也不是沒有東西不值得被記錄的,相反,這段時間中許許多多的事情都是第一次,若是一切就...
    章迪了閱讀 167評論 0 0