03.03 MySQL分庫分表之後,id主鍵如何處理?

zhengrong8247


數據庫在做了分庫分表之後,關於ID主鍵,我認為需要考慮這幾點:


生成算法

當我們的數據庫是單臺的時候,是不用太操心主鍵的生成,但是當數據庫進行了分庫分表之後,那麼主鍵的生成就需要注意了,至少不能使用數據庫內部的自增長序列了,通常要引入分佈式唯一標識碼的生成算法。

  • 利用數據庫生成:先說最笨的方法,利用數據庫的自增長序列生成,數據庫內唯一,有人會說,剛說完不能用數據庫的自增長序列,這麼快就要被打臉了麼?其實這個的意思是,先利用(額外)的一臺數據庫,通過其自增長序列得到主鍵,然後作為分庫分表的主鍵;

  • 利用Redis/MongoDB/zookeeper生成:Redis的單線程的,利用incr和increby;MongoDB的ObjectId;ZK通過znode數據版本;都可以生成全局的唯一標識碼;

  • UUID:生成唯一標識碼最常用的算法之一;

  • Snowflake:Twitter開源,基於zk,41位時間戳(毫秒數)+10位機器的ID+12位毫秒內的流水號+1位符號位(永遠是0);

  • UidGenerator:百度開源,基於snowflake算法;

  • Leaf:美團開源,能保證全局唯一性、高可用、趨勢遞增(不太安全,比如洩露公司訂單數量)、單調遞增等。


擴容會比較麻煩

分庫分表通常的方案都用主鍵mod分表的數量,來把數據路由到某一個數據庫分片上。例如分了10張表,那麼就是ID%10,得到結果0-9,代表不同的表;但是當數據量進一步增多的時候,單庫的數據量達到了一定的級別之後,那麼就需要分更多的表,那麼這時候有哪些處理方案呢?

  • 做數據遷移:最簡單暴力,也是最麻煩的一個方案;因為當分表(分庫)數量增多的時候,因為分片規則的變化,每個表的數據都要被重新分配到多個新的表;

  • 如果id是一個增長的全局序列,當前有十張表,那麼分表的算法為:id%10,根據0-9路由到10個表中;當表擴到20張的時候,擴容那一刻取max_id,那麼未來分庫的算法也就變成了:

if(id
  • 有些分表的算法本身就帶時間戳,可以基於id中的時間戳來實現,比如Snowflake算法(見上文),這個算法是一個64位的Long值,前42位就是一個精確到毫秒的時間戳,那麼我們的分庫算法也就可以以某個時間點來判斷:

if(id中的時間

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


我從分庫分表存在的問題和怎麼做來回答一下這個問題。。

一,分庫分表的ID主鍵不能依賴於數據庫的自增,因為多庫中會重複!

通常使用外接的數據組件獲取全局唯一的ID:比如加強型UUID(根據Ip,時間戳等得到)和使用Redis(RedisAtomicLong)和zookeeper的API獲取,Twitter的雪花算法等等!

二,分庫分表之後的連接查詢比較困難!

問題沒法避免,通常拆分SQL,使用多次查詢,用查到的結果再分別查別的結果!

三,分佈式事務的數據一致性很難保證!

可以使用TCC編程模型保證兩處的事務都能正確提交,但是這種方式對代碼的侵入比較重!也可以使用基於消息的數據一致性保證!

四,多數據的排序,分組,統計會比較困難!

1,用多線程,對多個節點分別查詢,然後彙總!

2,也可以提前冗餘查詢表,將所有的經常查詢的重點數據提前統一到個庫表裡!

分庫分表涉及到的知識點比較多,建議使用專門的分庫分表組件!本人有mycat使用經驗,如果您有相關問題,歡迎前來探討!


此生唯一


數據量達到查詢瓶頸的時候,需要做一些拆分或索引優化處理。

對於使用id主鍵來說,分庫分表都要做一些特別的設計,有以下幾個方案。

1、id區間提前規劃好,每個庫分配好整數區間,每個庫中的每個表也要規劃號,數字那麼大,總有區間能夠容納下增長的數字。

2、id採用32位全局uuid保證唯一

3、通過雪花算法,得到分佈式環境下全局唯一的id

4、採用納秒級時間戳+隨機數+重試機制保證數據唯一。

由於數據庫的索引大部分採用B+數數據結構來存儲,主鍵的線性遞增對數據的插入(B+樹的拆分和合並)和查詢性能有優勢,所以建議採用能保證主鍵遞增的方案。


木星上的程序員


全局id生成算法 snowklake算法 用long型64位表示 1位表示符號位正整數 41位表示時間戳 10位表示機器碼 12位表示順序位


浩哥仔


看你怎麼分,但無論怎麼分都要保留或新建主建來關聯數據,數據關聯不起來,就廢了。


hans9527


為什麼要分物理表呢? 分區的底層同樣是物理分表但上層MySQL已做好一切展現給我們的是一個總表,不同的數據放到不同分區,CURD甚至索引完全就是當成一個表來操作,其實展現給用戶的就是一張表,但底層分成了若干個區


蕩頭


苞米豆的mybatis-plus,只需要配置一下就可以,但我沒有實際應用過


霸天成ak


寫個api,專門用來生成唯一id,用他來做主鍵


SQL老碼農


id主鍵不用管。MySQL自己會處理。無非是操作的時候不一樣


三門峽的三


使用中間件吧 類似mycat


分享到:


相關文章: