探索C#之虛擬桶分片


閱讀目錄

  1. 背景
  2. 虛擬桶(virtual buckets)
  3. 實現
  4. 總結

背景

關於數據分片討論最多的是一致性hash,然而它並不是分布式設計中的銀彈百試百靈。 在數據穩定性要求比較高的場景下它的缺點是不能容忍的。
比如在Redis分布式緩存設計中,使用一致性Hash進行key分片存儲,通過虛擬節點最大化降低添加或刪除節點帶來的影響。這里強調降低二字,即是它還是有影響的,在一般情況下我們還可以接受。
但是某些場景下要求動態擴容無影響就無法滿足了。

上次(探索c#之一致性Hash詳解)提到過Hash取模的分片算法,是把數據mod后直接映射到真實節點上面,這造成節點個數和數據的緊密關聯、后期缺乏靈活擴展。
而一致性Hash分片算法多增加一層虛擬映射層,數據與虛擬節點映射、虛擬節點與真實節點再映射。

虛擬桶(virtual buckets)

虛擬桶是取模和一致性hash二者的折中辦法。

  • 采用固定節點數量,來避免取模的不靈活性。
  • 采用可配置映射節點,來避免一致性hash的部分影響。

其運行機制如下:

key對虛擬桶層

虛擬桶層采用預設固定數量,比如樓主在項目中預設N=1024。意味之后這個分布式集群最大擴容到1024個節點,帶來的好處就是mod后的值是不變的(非常重要),這保證了第一層映射挖寶去不受實際節點變化的影響。 關於最大數量,可根據實現需要預先定義好即可,比如Redis官方的糟最大65000個節點,豌豆莢的codis默認也是1024個節點。 當然如果數據量超過1024節點存儲時,可以再起另外個集群應對。

虛擬桶對實際節點

舉個例子,項目剛開始使用時配置節點映射:
Redis Server1對應桶的編號為0到500。
Redis Server2對應桶的編號為500到1024。

緩存數據量增長后需要增加新節點,在加之前需要重新分配節點對應虛擬桶的編號。 比如增加server3並配置對應桶的編號400到600,這時對於key映射虛擬桶層完全無影響。  實際上mod 400到600的真實數據還在另外兩台節點上,請求過來后還會發生無法命中的影響。
這就要求在增加新節點前,需要在后台把另外二台的400到600編號數據拷貝到新節點上面,完成后再添加配置到映射上面。 因為新來請求會命中到新節點,所以另外2台的400到600編號數據就無用了,需要進行刪除。這種做法就能最大限度(100%)的保證動態擴容后,對緩存系統無影響。

實現

算法實現這塊比較簡單,數據遷移、配置等這塊需要單獨的系統來做。

private Dictionary<int, RedisGroup> RedisGroups;
private const ulong Slot = 1024;

 public RedisGroup GetGroup(string key)
        {
            var longVal = Md5Hash(key);
            var index = (int) (longVal%Slot);
            return RedisGroups[index];
        }

        public ulong Md5Hash(string key)
        {
            using (var hash = System.Security.Cryptography.MD5.Create())
            {
                byte[] data = hash.ComputeHash(Encoding.UTF8.GetBytes(key));
                var a = BitConverter.ToUInt64(data, 0);
                var b = BitConverter.ToUInt64(data, 8);
                ulong hashCode = a ^ b;
                return hashCode;
            }
        }

總結

采取虛擬桶這種預分片的算法,可以避免一致性hash擴容時引起的緩存不命中。文中使用1024個實例作為最大節點數量,實際中是完全足夠用的。如果以后可能超過這個數量,可以部署另外一套1024節點的集群,最后形成一個超大規模的redis集群。

關於Redis的整套解決方案可以參考使用豌豆莢的codis。

分享了項目中一些使用經驗,希望對大家有所幫助。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM