Mysql分庫分表的主鍵生成演算法

2021-10-08 17:40:29 字數 1527 閱讀 2487

mysql單錶在資料量超過千萬的時候,效能就會受到極大的影響。尤其是對於不命中索引的請求,破壞性是難以想象的。當單錶的資料量達到一定程度的時候,我們就需要進行分表或者表分割槽了。分表面臨的第乙個問題就是主鍵id生成的問題,因為涉及到多表,所以原本單錶的自增id生成已經不可用了。那麼我們就需要生成全域性的id,有兩種方法供我們選擇,兩者也各有優缺點。

最常見的演算法就是利用外部的儲存,例如redis、mysql或者zookeeper來實現。上述三者比較推崇的是用redis來實現,因為redis是單執行緒架構,同時天生是為高併發而生,而且實現起來是比較簡單的。對於mysql的話有點重,大家都懂,效能實在不如redis。對於zookeeper的話,場景不是很適用,你可以建立順序的臨時節點來生成id,但是這確實不是zookeeper擅長的,就像拿著鐵鍬切白菜。同時zookeeper對於高併發場景實在是不行。例如,某東雙十一的服務**事件....。但是上面這些實現多少都有些臃腫。因為你需要去依賴乙個第三方的東西,而僅僅是為了生成乙個id。第三方系統的可用性,也直接決定了你系統的可用性。這種依賴確實是有些重。所以我們需要更輕量級的id生成方案。

相比上面依賴第三方生成id,那麼利用演算法生成簡直是輕量,效能也是遠遠高於上面的方法。但是有幾個關鍵的點:

1.對於資料庫來說,對於隨機id的插入會導致索引頁頻繁**,這樣會使插入操作變慢,索引頁碎片越來越嚴重。所以成演算法需要能保證生產id有序。

2.現在的後台都是服務化的,那麼這樣生成演算法要保證,無論在哪個節點都要保證生成的id都是全域性唯一的。

3.生成的id需要有比較強的隨機性,這樣在分表的時候可以盡可能的均勻分布。

這樣看來,這樣的生成演算法確實是比較困難的,下面我們就實現乙個這樣的id生成演算法。

首先,我們需要確定乙個隨機因素,這應該是乙個隨機遞增的因子,那麼時間戳無疑十分合適,線上伺服器往往都有全域性統一的時間。我們可以用時間戳遞增的特點,來保證id遞增。

同時我們需要乙個標識來區分不同的機器,這樣能在同一毫秒衝突下,解決衝突問題。

但是光有機器的衝突解決還是不夠的,在高併發場景下,同一毫秒會有很多的請求,我們需要解決一台機器的高併發問題,我們可以使用乙個遞增的序列號,來保證一台機器上的id是有序的。

那麼id就變成了下面的格式:

這樣就解決了id生成的問題,但是好像還有一些問題沒解決,id的長度怎麼控制,分表的路由規則怎麼確定?

首先,對於id長度的確定,上面的id規則裡,機器id和衝突遞增號基本是不會更改的,我們可以決定乙個seed,來生成字首時間戳,可以用當前時間戳減去seed,這樣可以通過控制seed的長度來控制字首時間戳的長度,進而控制id的長度。

對於分表的路由規則,如果我們利用id取模來實現路由,其實是不能保證均勻的,因為後面機器id和衝突的序列號對路由取模是有很大影響的,所以我們可以利用位移運算來取字首的時間戳,因為字首時間戳是全域性順序的,那麼做分割槽路由的時候也會是盡可能均勻的。

其實id的生成演算法是比較簡單的,但是使用過程中還是有很多問題的,比如id長度,看上去沒什麼大礙。但是對於一些對接其他系統的場景,id可能會讓你痛不欲生,而洗資料也是體力活兒。如果id過長極容易產生前端顯示問題,畢竟js的long是15位的。所以實際運用中id長度也要嚴格把控。

mysql分表分庫實現 MySql分表分庫思路

一.資料庫瓶頸 1.1io瓶頸 第一種 磁碟讀io瓶頸,熱點資料太多,資料庫快取放不下,每次查詢時會產生大量的io 分庫和垂直分表 第二種 網路io瓶頸,請求的資料太多,網路頻寬不夠 分庫 1.2cpu瓶頸 第一種 sql問題,如sql中包含join,group by,order by,非索引字段條...

MySQL範圍分表分庫 mysql 分表分庫策略

唯一id的生成 下面列舉幾種常見的唯一id生成方案,需要滿足兩大核心需求 1.全域性唯一 2趨勢有序 1.用資料庫的auto increment 自增id 來生成,每次通過寫入資料庫一條記錄,利用資料庫id自增的特性獲取唯一,有序的id。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...

mysql 分庫分表實戰 MySQL分庫分表實戰

為什麼要分庫分表 在大型 中,當使用者量以及使用者產生的業務資料量達到單庫單錶效能極限時,為了支撐業務可持續發展,對於重要的核心業務必然要進行分庫分表來儲存業務資料。對於非核心業務產生的大量資料,例如爬蟲爬取的資訊,論壇產生的資料等,可以考慮把資料儲存在像mongodb這樣的nosql儲存裡面,這些...