PHP實現Snowflake生成分布式唯一ID

2021-09-13 01:21:07 字數 2204 閱讀 7148

twitter 的 snowflake 在分布式生成唯一 uuid 應用還是蠻廣泛的,基於 snowflake 的一些變種的演算法網上也有不少。使用 snowflake 生成 uuid 很多都是在分布式場景下使用,我看了下網上有其中有幾篇 php 實現的都沒有考慮到執行緒安全。現在 php 有了 swoole 的鎖和協程的加持,對於我們開發執行緒安全和高併發模擬還是很方便的,這裡用 php 結合 swoole 來學習下實現最簡單的 snowflake(好久沒寫 php,感覺沒有 ide 真寫不了 php 了)。

先來看以下 snowflake 的結構:

生成的數值是 64 位,分成 4 個部分:

先貼下**:

<?php 

class snowflake

$this->timestamp = 0;

$this->workerid = $workerid;

$this->sequence = 0;

$this->lock = new swoole_lock(swoole_mutex);

}/**

* 生成id

* @return int

*/public function getid()

}} else

$this->timestamp = $now; // 更新id生時間戳

$id = (($now - self::epoch) << self::time_shift) | ($this->workerid << self::worker_shift) | $this->sequence;

$this->lock->unlock(); //解鎖

return $id;

}/**

* 獲取當前毫秒

* @return string

*/public function now()

}

其實邏輯並不複雜,解釋一下**中的位運算:

-1 ^ (-1 << self::sequence_bits)

就是-1的二進位制表示為1的補碼,其實等同於 :

2**self::sequence_bits - 1

最後部分左移後或運算:

(($now - self::epoch) << self::time_shift) | ($this->workerid << self::worker_shift) | $this->sequence;
這裡主要是對除了第一位符號位以外的三個部分進行左移相應的偏移量使其歸位,並通過或運算重新整合成上面 snowflake 的結構,比如我們用 3 部分 4 位來演示一下該歸併操作:

0000 0000 0010  --左移0位--> 0000 0000 0010

0000 0000 0100 --左移4位--> 0000 0100 0000 --或操作-->1000 0100 0010

0000 0000 1000 --左移8位--> 1000 0000 0000

下面借助 swoole 的協程和 channel 來暴力測試一下,看看生成的 id 是否會出現重複的狀況:

$snowflake = new snowflake(1);

$chan = new chan(100000);

$n = 100000;

for ($i = 0; $i < $n; $i++) );

}go(function () use ($chan, $n)

array_push($arr, $id);

}});$chan->close();

echo "ok";

跑了一下,確實不會出現重複的 id,對了,我用 golang 同樣實現了 snowflake 並協程式方式跑了同樣的測試,php 的執行時間是大約 12 秒左右,golang 只需要 1 秒。文章有什麼錯誤還請指正,謝謝。

如果覺得本篇文章對您十分有益,何不 打賞一下

php 實現 snowflake 生成分布式唯一 id

PHP生成唯一ID之SnowFlake演算法詳解

snowflake演算法是個啥?首先我來提出個問題,怎麼在分布式系統中生成唯一性id並保持該id大致自增?在twitter中這是最重要的業務場景,於是twitter推出了一種snowflake演算法。前言 最近需要做一套cms系統,由於功能比較單一,而且要求靈活,所以放棄了wp這樣的成熟系統,自己做...

C 實現 Snowflake演算法生成唯一性Id

動態生產有規律的id public class snowflake public snowflake public snowflake long machineid public snowflake long machineid,long datacenterid private void snow...

php 生闢字陣列處理

最近在做專案的時候 專案和資料庫是gbk的 好多地方需要轉碼 找了一些資料 寫下來 方便以後再遇到好找 ajax 呼叫城市的時候 香港的一些城市是生闢字 返回 false city get resume city pid arr eval return iconv gb2312 utf 8 var ...