雲棲號資訊:【點擊查看更多行業資訊】
在這裏您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
背景
隨着應用的越做越大,數據量越來越多,不論是MySQL數據庫的單庫單表還是單臺redis都無法滿足高併發的讀寫操作和大數據量的存儲功能,因此有了大家耳熟能詳的分庫分表。
垂直拆分和水平拆分
垂直拆分,即拆分列,從業務上將原來一個表的信息拆到兩個表中,形象的理解爲垂直的一把刀切開了表
水平拆分,即拆分行,通過某種規則將一個表中的數據拆分到不同的表中,形象的理解爲水平的一把刀切開了表
當然垂直拆分和水平拆分的概念不是本文要討論的重點,本文要討論的是水平拆分的規則。水平拆分的本質其實和分佈式系統下微服務的思想不謀而合,微服務的出現筆者前文提到過是因爲單個服務承載了太多的業務邏輯,導致出現了諸如代碼邏輯龐大複雜、開發人員關係耦合、單點故障等問題。這些問題對於DB和redis同樣會有:
- 當訪問請求越來越多時,單機的DB/redis無法分配足夠的線程抗住高併發的請求
- 當數據量越來越大時,從一碗水中找一根針和從一片大海中找一根針的難度和耗時也是不一樣的,我們要做的是找到那個碗,然後從碗裏撈針
所以我們需要將DB/redis擴展爲多臺。
幾種分佈式集羣中的路由算法
相信前面的介紹已經說明了水平拆分的必要性,現在的問題就是如何拆分,按何種規則將不同的數據歸類到不同的mysql庫/mysql表/redis機器上。下面我們以userid作爲key爲例。
固定哈希
固定哈希很好理解,筆者現在所在的部門數據庫的分庫分表邏輯就是簡單的 (userid % 32) ^ (userid >> 32),取了userid的高32位和低32位進行了與運算。
這麼做的好處是邏輯簡單,相信這也是很多公司db業務的分庫分表方法,如果能夠保證用戶的id能夠均勻分佈在每個分片上。
缺點是伸縮性差,當需要新增服務時,新機器根本路由不到;當需要下線服務時,由於固定哈希必然會導致請求到該服務的請求失敗。
一致性哈希
一致性哈希帶來的最大變化就是把節點對應的哈希值變成了一個範圍,可以將一致性哈希想象成一個環形的鐘表,現在我們在12點、4點、8點鐘反向分別有三臺機器,這時候我們算出hash(key)之後就去找離它最近的機器節點
例如這裏hash(key)=2,則找到了4點鐘方向的節點
一致性哈希雖然能夠穩定的將請求切換到新機器,但是它也有一些小缺陷。因爲 hash取模算法得到的結果是隨機的,我們並不能保證各個服務節點能均勻的分配到哈希環上,這就導致了經典的熱點問題,又叫數據傾斜問題,例如如圖情況會導致8點鐘服務承受了過多的負載。
引入虛擬節點的一致性哈希
爲了應對上面的問題,我們引入了虛擬節點的概念,我們通過對每個機器映射出多個hash,
hashA = hash("192.168.0.1-A") % 32
hashB = hash("192.168.0.1-B") % 32
hashC = hash("192.168.0.1-C") % 32
從而實現一個機器在環上有多個虛擬節點,如圖
自定義計算方式
如上文所述,筆者所在的公司前期的分庫規則是固定哈希,但是隨後結合業務實際表現來看有部分用戶(稱爲大戶)訪問量是小用戶的n倍,和普通用戶路由到一個db或redis中勢必會影響到普通用戶的讀寫,因此對於這些特殊的戶單獨做了一個規則路由到分片號爲9999的特殊分片。
以上這種模式其實就是自定義計算方式。
【雲棲號在線課堂】每天都有產品技術專家分享!
課程地址:https://yqh.aliyun.com/live立即加入社羣,與專家面對面,及時瞭解課程最新動態!
【雲棲號在線課堂 社羣】https://c.tb.cn/F3.Z8gvnK
原文發佈時間:2020-08-01
本文作者:ackpotDC
本文來自:“掘金”,瞭解相關信息可以關注“掘金”