論數據分片技術及其應用
信1805-2班 20183583 張志偉
數據分片就是按照一定的規則,將數據集划分成相互獨立正交的數據子集。然后將數據子集分布到不同的節點上,通過設計合理的數據分片規則,可將系統中的數據分布在不同的物理數據庫中,達到提升應用系統數據處理速度的目的。在解決數據庫日志解析的問題中,我承擔了進行數據分片的任務。
數據分片,就是依照分片算法將數據打散到多個不同的節點上,每個節點上存儲部分數據。一般來說,分片算法最常見的就是Hash分片、一致性Hash分片和按照范圍數據分片三種。下面將對這三種分片技術進行簡單的闡釋,並介紹在數據庫日志解析中采用的分片方式。
Hash分片
Hash 分片的算法就是對緩存的 Key 做哈希計算,然后對總的緩存節點個數取余。你可以這么理解:比如說,我們部署了三個緩存節點組成一個緩存的集群,當有新的數據要寫入時,我們先對這個緩存的 Key 做比如 crc32 等 Hash 算法生成 Hash 值,然后對 Hash 值模 3,得出的結果就是要存入緩存節點的序號。
這個算法最大的優點就是簡單易理解,缺點是當增加或者減少緩存節點時,緩存總的節點個數變化造成計算出來的節點發生變化,從而造成緩存失效不可用。所以我建議你,如果采用這種方法,最好建立在你對於這組緩存命中率下降不敏感,比如下面還有另外一層緩存來兜底的情況下。那有沒有更好的方案能解決這個問題呢?那就是一致性 Hash 分片算法。
一致性Hash分片
用一致性 Hash 算法可以很好地解決增加和刪減節點時,命中率下降的問題。在這個算法中,我們將整個 Hash 值空間組織成一個虛擬的圓環,然后將緩存節點的 IP 地址或者主機名做 Hash 取值后,放置在這個圓環上。當我們需要確定某一個 Key 需要存取到哪個節點上的時候,先對這個 Key 做同樣的 Hash 取值,確定在環上的位置,然后按照順時針方向在環上“行走”,遇到的第一個緩存節點就是要訪問的節點。比方說下面這張圖里面,Key 1 和 Key 2 會落入到 Node 1 中,Key 3、Key 4 會落入到 Node 2 中,Key 5 落入到 Node 3 中,Key 6 落入到 Node 4 中。
這時如果在 Node 1 和 Node 2 之間增加一個 Node 5,你可以看到原本命中 Node 2 的 Key 3 現在命中到 Node 5,而其它的 Key 都沒有變化;同樣的道理,如果我們把 Node 3 從集群中移除,那么只會影響到 Key 5 。所以你看,在增加和刪除節點時,只有少量的 Key 會 漂移 到其它節點上,而大部分的 Key 命中的節點還是會保持不變,從而可以保證命中率不會大幅下降。
不過,事物總有兩面性。雖然這個算法對命中率的影響比較小,但它還是存在問題:
- 緩存節點在圓環上分布不平均,會造成部分緩存節點的壓力較大;
- 當某個節點故障時,這個節點所要承擔的所有訪問都會被順移到另一個節點上,會對后面這個節點造成壓力。
按照數據范圍分片
常見場景就是按照 時間區間 或 ID區間 來切分。例如:按日期將不同月甚至是日的數據分散到不同的庫中;將 userId 為 1~9999 的記錄分到第一個庫, 10000~20000 的分到第二個庫,以此類推。某種意義上,某些系統中使用的 "冷熱數據分離" ,將一些使用較少的歷史數據遷移到其他庫中,業務功能上只提供熱點數據的查詢,也是類似的實踐。
這樣的優點在於: - 單表大小可控
- 天然便於水平擴展,后期如果想對整個分片集群擴容時,只需要添加節點即可,無需對其他分片的數據進行遷移
- 使用分片字段進行范圍查找時,連續分片可快速定位分片進行快速查詢,有效避免跨分片查詢的問題。
缺點: - 熱點數據成為性能瓶頸。連續分片可能存在數據熱點,例如按時間字段分片,有些分片存儲最近時間段內的數據,可能會被頻繁的讀寫,而有些分片存儲的歷史數據,則很少被查詢。
數據庫日志解析進行分片
在解析數據庫日志的過程中,為了提高日志數據的解析和查找效率,也要進行分片。查找日志的過程中有一些關鍵的變量數值:事務日志的唯一標識就是TransactionID,事務的操作類型Operation主要是分為增刪改三類,AllocUnitName是事務操作的數據表名稱,再有就是事務的開始時間BeginTime和結束時間EndTime。在進行分片時,可以采用的分片技術有三種:Hash分片、一致性Hash分片和按照數據范圍分片。
在進行日志分析時,假定要使用Hash分片,那么可以根據TransactionID進行分片,但這樣分片的意義並不大,因為只是單純的將數據分開,但並沒有方便后續的查找和分析。我們最終采用的是按照數據范圍分片,首先,可以按照時間段進行分片,因為如果最終要做成一個數據庫同步軟件,我們需要做的工作,是要在能夠解析日志的基礎上加上定時任務,按照時間段進行分片,可以說是將每次同步的任務單獨存放,這樣分片不僅減小了每個分片的數據量,也方便后續出現問題時,進行按照任務進行排查,也便於統計每次任務所完成的數據量,操作類型。亦或是按照操作類型進行分片,將增刪改的分別單獨存放,這樣的類型區分明顯,降低了后續統計的工作量。也可以按照所操作的表進行分片,方便在進行數據增量同步時直接在對應的表進行操作,也可以給每一個表設置一個線程,提高效率。
綜合上面的幾種設想,在最終進行數據分片時,先按照時間段進行划分,也就是每次的同步任務是一個分片,在此基礎上按照所操作的表對象進行分,然后在按照操作類型分,這樣分完之后,單個分片的數據量大大減少,在進行查詢統計時,也可以根據需要來對這些小的分片按照需要進行組合,直接得到大部分想要的結果,大幅提高了執行效率。
小結
數據分片可以提高程序的可擴展性,提高性能,從而能夠支持起更加龐大的數據規模,當然分片也有不好的地方,因為數據進行了分片導致了數據過於分散,在進行數據備份和遷移時就會耗費更大的精力。