很久沒更新了,慚愧,今日剛好又學了一新招,特此記錄。
以前寫過一篇文章,《分布式環境下建立唯一id》。在那個時候,最終定下來的id組成結構是:
time | sequence | index
32 19 13
頭32位是時間戳;
中間19位是遞增序號,每秒重置;
最後13位是固定的序號;
由於原來只考慮了insert,update因為有批量操作所以並沒有讓update時更新這一唯一id,否則同樣where出來的結果集去更新該id,肯定報duplicate primary key。
為了讓批量update時,為每一條更新的row,自動生成新的唯一id,在現有架構下,只能從資料庫找辦法了。
假定test表表結構如下:
fv| f1|f2
其中fv即是全schema唯一id。該語句找到f1字段值為2的批量更新fv和f2。
執行後,看到where結果集中,f2全部變成相同的時間戳值。而fv完全沒有重複。
取更新時間即為
select from_unixtime(fv>>32) from test;
於是了這樣一條語句:
update test t, (select @count:=0)b
set fv=(unix_timestamp(current_timestamp)<<32 | (@count:=@count+1)<<13 | 97) , f2=(unix_timestamp(current_timestamp)<<32)
where t.f1='2';
這裡@count的值,每一次執行sql時,會重置為0,所以基本上不用擔心溢位(19位應該夠用了,不會一次性更新這麼多)。
序號的話,不同的寫入節點分配不同的序號,每次生產sql的時候,動態拼接就好了。
但是想想,還是不對,同乙個節點下兩個不同執行緒如果剛好執行乙個相同where語句,那麼彼此@count不共享,都是從0開始,依然會造成fv相同。
還好mysql有個uuid_short()的方法,通過以下方式生成唯一鍵
(server_id & 255) << 56
+ (server_startup_time_in_seconds << 24)
+ incremented_variable++;
server_id是資料庫instance的編號,不能超過255。
這個uuid_short()可以產生乙個64位的全庫唯一id,剛好可以用,考慮到它的低位都是遞增的,所以並不需要取完整的64位,只需要取後面部分的值就行了,即
update test set fv=(unix_timestamp(current_timestamp)<<32 | right(uuid_short(),8)) where f1='2'
這裡取字串後面8位的值,拼接到低32位,十進位制8位最大值99999999,26位即可滿足,所以也不會溢位。
這個方案連低13位的序號都省了。完全可以滿足分布式的需求。
另外簡單做了下壓力測試,結果還可以。不過仍需長期觀察下有沒有其他影響。
odoo 分布式快速更新
如果odoo 服務太多的話,乙個乙個的重啟會比較麻煩 寫乙個python指令碼來批量重啟 import paramiko import configparser def get conf cf configparser.configparser cf.read data server.conf se...
klock 分布式鎖重大更新
開發四年只會寫業務 分布式高併發都不會還做程式設計師?基於redis的分布式鎖spring boot starter元件,使得專案擁有分布式鎖能力變得異常簡單,支援spring boot,和spirng mvc等spring相關專案。基於註解驅動,支援spring spel,方便的定義鎖的key的粒...
分布式ID詳解
分布式id 用在分布式系統中 在我們的業務需求中通常有需要一些唯一的id,來記錄我們某個資料的標識 1.如果id我們使用的是資料庫的自增長型別,在分布式系統中需要分庫和分表,會有兩個相同的表,有可能產生主鍵衝突 根據資料庫的儲存結構來定,mysql底層用的是innodb引擎,底層儲存結構是b 樹,大...