最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

KV存儲(chǔ)(Squirrel、Cellar架構(gòu))

2022-11-06 19:59 作者:苦茶今天斷更了嗎  | 我要投稿


KV存儲(chǔ)(Squirrel、Cellar架構(gòu))

NoSQL存儲(chǔ):非關(guān)系型數(shù)據(jù)庫(kù),它以鍵值對(duì)存儲(chǔ),結(jié)構(gòu)不固定,可減少時(shí)間和空間開(kāi)銷(xiāo)。

KV存儲(chǔ)(鍵值存儲(chǔ)、Key-Value存儲(chǔ))是NoSQL存儲(chǔ)的一種方式。值可以是任意不定長(zhǎng)數(shù)據(jù)。非常適合不涉及過(guò)多數(shù)據(jù)關(guān)系業(yè)務(wù)關(guān)系的業(yè)務(wù)數(shù)據(jù),同時(shí)能有效減少讀寫(xiě)磁盤(pán)的次數(shù)。

KV存儲(chǔ)的數(shù)據(jù)主要分兩種:結(jié)構(gòu)數(shù)據(jù)(關(guān)系表),非結(jié)構(gòu)數(shù)據(jù)(大文件,雜數(shù)據(jù))。

?

??關(guān)系型數(shù)據(jù)庫(kù)中的表都是存儲(chǔ)一些格式化的數(shù)據(jù)結(jié)構(gòu),便于表與表之間進(jìn)行連接等操作,但也是關(guān)系型數(shù)據(jù)庫(kù)性能瓶頸的一個(gè)因素。它不能滿足以下“高”需求:

①對(duì)數(shù)據(jù)庫(kù)高并發(fā)讀寫(xiě)的需求;

②對(duì)海量數(shù)據(jù)的高效率存儲(chǔ)和訪問(wèn)的需求;

③對(duì)數(shù)據(jù)庫(kù)的高可擴(kuò)展性和高可用性的需求

為了解決這類(lèi)問(wèn)題,非關(guān)系數(shù)據(jù)庫(kù)應(yīng)運(yùn)而生。Google的BigTable與Amazon的Dynamo是非常成功的商業(yè)NoSQL實(shí)現(xiàn)。一些開(kāi)源的NoSQL體系,如Membase,MongoDB,Cassandra,BeansDB,Redis等,也得到了廣泛認(rèn)同。

?

鍵值對(duì)存儲(chǔ)不需要了解值中的數(shù)據(jù),也沒(méi)有任何結(jié)構(gòu)。這同時(shí)表示像SQL那樣用WHERE語(yǔ)句或者通過(guò)任何形式的過(guò)濾來(lái)請(qǐng)求數(shù)據(jù)中的一部分是無(wú)法做到的。如果你不知道去哪找,你必須遍歷所有的鍵,即表示只有當(dāng)鍵已知的時(shí)候才能體現(xiàn)出最佳性能(注意:一些鍵值對(duì)存儲(chǔ)能夠存儲(chǔ)結(jié)構(gòu)化的數(shù)據(jù)并有字段索引)。

因此,即使鍵值對(duì)存儲(chǔ)在訪問(wèn)速度上經(jīng)常比關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)性能要好數(shù)個(gè)數(shù)量級(jí),但對(duì)鍵已知的需求也限制著其應(yīng)用。

?

?

分布式存儲(chǔ)系統(tǒng)

1、分布式文件系統(tǒng):存儲(chǔ)文本,圖片,音視頻等非結(jié)構(gòu)化數(shù)據(jù)。

2、分布式鍵值系統(tǒng):存儲(chǔ)簡(jiǎn)單的半結(jié)構(gòu)化數(shù)據(jù)。

NoSql的分布式擴(kuò)展,只提供基于key的增刪改查功能。

3、分布式表格系統(tǒng):存儲(chǔ)復(fù)雜的半結(jié)構(gòu)化數(shù)據(jù)。

相較于分布式kv系統(tǒng),他還支持基于key的范圍查找。

相對(duì)于關(guān)系型數(shù)據(jù)庫(kù),他不支持復(fù)雜的操作,如多表關(guān)聯(lián),嵌套查詢。

4、分布式數(shù)據(jù)庫(kù):存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)。分布式的關(guān)系型數(shù)據(jù)庫(kù)。提供SQL關(guān)系查詢語(yǔ)言。

?

單機(jī)存儲(chǔ)引擎

1、哈希存儲(chǔ):hash的CRUD是最快的。缺點(diǎn):不支持順序掃描。

2、B樹(shù):支持隨機(jī)讀取、范圍查找的系統(tǒng)。查找時(shí)間復(fù)雜度為log(d(n))(d為每個(gè)節(jié)點(diǎn)的出度)。

3、LSM樹(shù)(Log Structured Merge Tree):將增量寫(xiě)操作保存在內(nèi)存中,超過(guò)閾值時(shí)刷入磁盤(pán),從而減少隨機(jī)寫(xiě)磁盤(pán)操作。讀操作則需要合并磁盤(pán)數(shù)據(jù)和內(nèi)存中的寫(xiě)操作。

?

RocksDB

相對(duì)傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)采用了LSM樹(shù)存儲(chǔ)引擎。

主要設(shè)計(jì)目標(biāo)是保證存取快速存儲(chǔ)器和高負(fù)載服務(wù)器更高效,保證充分利用Flash或RAM子系統(tǒng)提供的高速率讀寫(xiě),支持高效的查找和范圍scan,支持高負(fù)載的隨機(jī)讀、高負(fù)載的更新操作或兩者的結(jié)合。其架構(gòu)應(yīng)該支持高并發(fā)讀寫(xiě)和容量大增時(shí)系統(tǒng)的一致性。

RocksDB是一個(gè)嵌入式鍵值存儲(chǔ)器,其中鍵和值是任意的字節(jié)流。RocksDB中的所有數(shù)據(jù)是按序存放的。常見(jiàn)操作包括Get(key),Put(key),Delete(key),Scan(key)。

RocksDB有三個(gè)基本結(jié)構(gòu):RocksDB memtable,sstfile,logfile。

memtable是一個(gè)內(nèi)存數(shù)據(jù)結(jié)構(gòu)——新數(shù)據(jù)會(huì)插入到memtable和日志文件(可選)。日志文件是順序?qū)懭氲?,位于磁盤(pán)。當(dāng)memtable寫(xiě)滿后,數(shù)據(jù)會(huì)被刷新到磁盤(pán)上的sstfile文件,同時(shí)相應(yīng)的日志文件可以安全地刪除。sstfile中的數(shù)據(jù)經(jīng)過(guò)排序的,目的是為了加快鍵查找。

分布式鍵值系統(tǒng):由多個(gè)RocksDB構(gòu)成的分布式鍵值系統(tǒng)。



KV 存儲(chǔ)發(fā)展歷程

第一代分布式KV存儲(chǔ)架構(gòu)(左圖)。在客戶端內(nèi)做一致性哈希,在后端部署很多的 Memcached 實(shí)例,實(shí)現(xiàn)了最基本的 KV 存儲(chǔ)分布式設(shè)計(jì)。

問(wèn)題:如在宕機(jī)摘除節(jié)點(diǎn)時(shí),會(huì)丟數(shù)據(jù);需要擴(kuò)容時(shí),一致性哈希會(huì)丟失一些數(shù)據(jù)等。

?

引入Redis(右圖的架構(gòu))。服務(wù)器端變成了Redis組成的主從結(jié)構(gòu)。當(dāng)節(jié)點(diǎn)宕機(jī)時(shí),可通過(guò)Redis哨兵完成Failover,實(shí)現(xiàn)高可用。

問(wèn)題:擴(kuò)縮容時(shí),一致性哈希仍然會(huì)丟數(shù)據(jù)。

一個(gè)比較成熟的KV存儲(chǔ)開(kāi)源項(xiàng)目:阿里Tair

Tair開(kāi)源版本的架構(gòu)主要分成三部分:存儲(chǔ)節(jié)點(diǎn)會(huì)上報(bào)心跳到它的中心節(jié)點(diǎn),中心節(jié)點(diǎn)內(nèi)部有兩個(gè)配置管理節(jié)點(diǎn),會(huì)監(jiān)控所有的存儲(chǔ)節(jié)點(diǎn)。當(dāng)有任何存儲(chǔ)節(jié)點(diǎn)宕機(jī)或者擴(kuò)容時(shí),它會(huì)做集群拓?fù)涞闹匦聵?gòu)建。當(dāng)客戶端啟動(dòng)時(shí),它會(huì)直接從中心節(jié)點(diǎn)拉來(lái)一個(gè)路由表(一個(gè)集群的數(shù)據(jù)分布圖),客戶端根據(jù)路由表直接去存儲(chǔ)節(jié)點(diǎn)讀寫(xiě)。

針對(duì)之前KV的擴(kuò)容丟數(shù)據(jù)問(wèn)題,它也有數(shù)據(jù)遷移機(jī)制來(lái)保證數(shù)據(jù)的完整性。

問(wèn)題:

①中心節(jié)點(diǎn)沒(méi)有類(lèi)似分布式仲裁的機(jī)制,在網(wǎng)絡(luò)分割的情況下,有可能發(fā)生“腦裂”。

②在容災(zāi)擴(kuò)容時(shí),數(shù)據(jù)遷移會(huì)影響業(yè)務(wù)可用性。

③Redis的數(shù)據(jù)結(jié)構(gòu)特別豐富,而Tair還不支持這些數(shù)據(jù)結(jié)構(gòu)。

redis官方發(fā)布集群版本Redis Cluster,演進(jìn)出全內(nèi)存、高吞吐、低延遲的KV存儲(chǔ) Squirrel。 基于Tair,演進(jìn)出持久化、大容量、數(shù)據(jù)高可靠的KV存儲(chǔ)Cellar。

如果業(yè)務(wù)的數(shù)據(jù)量小,對(duì)延遲敏感,建議用Squirrel ;

如果數(shù)據(jù)量大,對(duì)延遲不是特別敏感,建議用成本更低的Cellar。

?

內(nèi)存KV Squirrel架構(gòu)和實(shí)踐

先介紹兩個(gè)存儲(chǔ)系統(tǒng)共通的地方:分布式存儲(chǔ)問(wèn)題:Key是怎么分布到存儲(chǔ)節(jié)點(diǎn)上的?

拿到一個(gè)Key,用固定的哈希算法得到一個(gè)哈希值,將哈希值對(duì)Slot數(shù)目取模得到一個(gè)Slot id(兩個(gè)KV現(xiàn)在都是預(yù)分片16384個(gè)Slot),再根據(jù)路由表就能查到這個(gè)Slot存儲(chǔ)在哪個(gè)存儲(chǔ)節(jié)點(diǎn)上。這個(gè)路由表簡(jiǎn)單來(lái)說(shuō)就是一個(gè)Slot到存儲(chǔ)節(jié)點(diǎn)的對(duì)照表。

Key → H(key) → H(key) 對(duì)Slot數(shù)目取模 → Slot id?→ 路由表中查對(duì)應(yīng)哪個(gè)存儲(chǔ)節(jié)點(diǎn)

下圖為Squirrel架構(gòu)。中間部分跟Redis官方集群一致。它有主從的結(jié)構(gòu),Redis實(shí)例之間通過(guò)Gossip協(xié)議通信。添加了一個(gè)集群調(diào)度平臺(tái),包含調(diào)度服務(wù)、擴(kuò)縮容服務(wù)和高可用服務(wù)等,它會(huì)管理整個(gè)集群,把管理結(jié)果作為元數(shù)據(jù)更新到ZooKeeper??蛻舳藭?huì)訂閱 ZooKeeper上的元數(shù)據(jù)變更,實(shí)時(shí)獲取到集群的拓?fù)錉顟B(tài),直接在Redis集群進(jìn)行讀寫(xiě)操作。

?高可用架構(gòu):

從宏觀的角度來(lái)看,高可用就是指容災(zāi)怎么做;

從微觀的角度看,高可用就是如何保證端到端的高成功率;

?

Squirrel節(jié)點(diǎn)容災(zāi)——HA高可用服務(wù)

對(duì)于Redis集群而言,官方提供的方案,任何一個(gè)節(jié)點(diǎn)從宕機(jī)到被標(biāo)記為FAIL摘除,一般需要經(jīng)過(guò)30秒。主庫(kù)的摘除會(huì)影響數(shù)據(jù)的完整性,所以需要謹(jǐn)慎一些。從庫(kù)完全沒(méi)必要。

內(nèi)存的KV存儲(chǔ)數(shù)據(jù)量一般都比較小。若業(yè)務(wù)量很大,它往往會(huì)有很多的集群。如果發(fā)生交換機(jī)故障,會(huì)影響到很多的集群,宕機(jī)之后去補(bǔ)副本就會(huì)變得非常麻煩。為了解決這兩個(gè)問(wèn)題,做了HA高可用服務(wù)。

它的架構(gòu)如下圖所示,它會(huì)實(shí)時(shí)監(jiān)控集群的所有節(jié)點(diǎn)。不管是網(wǎng)絡(luò)抖動(dòng),還是發(fā)生了宕機(jī)(比如Redis 2),它可以實(shí)時(shí)更新ZooKeeper,告訴ZooKeeper摘除Redis 2,客戶端收到消息后,讀流量就直接路由到Redis 3上。如果Redis 2只是幾十秒的網(wǎng)絡(luò)抖動(dòng),HA節(jié)點(diǎn)監(jiān)控到它恢復(fù)后,會(huì)把它重新加回。

如果過(guò)了一段時(shí)間,HA 判斷它屬于一個(gè)永久性的宕機(jī),HA節(jié)點(diǎn)會(huì)直接從Kubernetes集群申請(qǐng)一個(gè)新的Redis 4容器實(shí)例,把它加到集群里。拓?fù)浣Y(jié)構(gòu)又變成了一主兩從的標(biāo)準(zhǔn)結(jié)構(gòu),HA節(jié)點(diǎn)更新完集群拓?fù)浜螅蜁?huì)去寫(xiě)ZooKeeper通知客戶端去更新路由,客戶端就能到Redis 4這個(gè)新從庫(kù)上進(jìn)行讀操作。

?  通過(guò)上述方案,把從庫(kù)的摘除時(shí)間從30秒降低到了5秒;把宕機(jī)補(bǔ)副本變成了一個(gè)分鐘級(jí)的自動(dòng)操作,不需要任何人工的介入。


?Squirrel跨地域容災(zāi)

①相對(duì)于同地域機(jī)房間的網(wǎng)絡(luò)而言,跨地域?qū)>€很不穩(wěn)定;

②跨地域?qū)>€的帶寬是非常有限且昂貴的。

?

如何通過(guò)集群同步服務(wù),把北京主集群的數(shù)據(jù)同步到上海從集群上?

按照流程,首先要向同步調(diào)度模塊下發(fā)“在兩個(gè)集群間建立同步鏈路”的任務(wù),同步調(diào)度模塊會(huì)根據(jù)主從集群的拓?fù)浣Y(jié)構(gòu),把主從集群間的同步任務(wù)下發(fā)到同步集群,同步集群收到同步任務(wù)后會(huì)扮成Redis 的Slave,通過(guò)Redis的復(fù)制協(xié)議,從主集群上的從庫(kù)拉取數(shù)據(jù),包括RDB以及后續(xù)的增量變更。同步機(jī)收到數(shù)據(jù)后會(huì)把它轉(zhuǎn)成客戶端的寫(xiě)命令,寫(xiě)到上海從集群的主節(jié)點(diǎn)里。

再加一個(gè)反向的同步鏈路,就可以實(shí)現(xiàn)集群間的雙向同步。


?

?如何做好微觀角度的高可用,也就是保持端到端的高成功率。對(duì)于Squirrel,主要講如下三個(gè)影響成功率的問(wèn)題:

  ①數(shù)據(jù)遷移造成超時(shí)抖動(dòng)。

②持久化造成超時(shí)抖動(dòng)。

③熱點(diǎn)Key請(qǐng)求導(dǎo)致單節(jié)點(diǎn)過(guò)載。

?

Squirrel智能遷移

  對(duì)于數(shù)據(jù)遷移,主要遇到三個(gè)問(wèn)題:

①Redis Cluster提供了數(shù)據(jù)遷移能力,但要遷哪些Slot,Slot從哪遷到哪,它并不管。

②遷移速度過(guò)快可能影響業(yè)務(wù)正常請(qǐng)求。

 ?、跼edis的Migrate命令會(huì)阻塞工作線程,尤其在遷移大Value時(shí)會(huì)阻塞特別久。

?

  為了解決這些問(wèn)題,做了全新的遷移服務(wù)。

首先生成遷移任務(wù),核心是就近原則”(如同機(jī)房的兩個(gè)節(jié)點(diǎn)做遷移肯定比跨機(jī)房的快。把任務(wù)下發(fā)到一批遷移機(jī)上。遷移機(jī)遷移的時(shí)候,有這樣幾個(gè)特點(diǎn):

  1、會(huì)在集群內(nèi)遷出節(jié)點(diǎn)間做并發(fā),比如同時(shí)給Redis 1、Redis 3下發(fā)遷移命令。

  2、每個(gè)Migrate命令會(huì)遷移一批Key。

  3、我們會(huì)用監(jiān)控服務(wù)去實(shí)時(shí)采集客戶端的成功率、耗時(shí),服務(wù)端的負(fù)載、QPS 等,之后把這個(gè)狀態(tài)反饋到遷移機(jī)上。遷移數(shù)據(jù)的過(guò)程就類(lèi)似TCP慢啟動(dòng)的過(guò)程,它會(huì)把速度一直往上加,若出現(xiàn)請(qǐng)求成功率下降等情況,它的速度就會(huì)降低,最終遷移速度會(huì)在動(dòng)態(tài)平衡中穩(wěn)定下來(lái),這樣就達(dá)到了最快速的遷移,同時(shí)又盡可能小地影響業(yè)務(wù)的正常請(qǐng)求。

?

對(duì)于大Value的遷移,實(shí)現(xiàn)了一個(gè)異步Migrate命令,該命令執(zhí)行時(shí),Redis的主線程會(huì)繼續(xù)處理其他的正常請(qǐng)求。如果此時(shí)有對(duì)正在遷移Key的寫(xiě)請(qǐng)求過(guò)來(lái),Redis會(huì)直接返回錯(cuò)誤。這樣最大限度保證了業(yè)務(wù)請(qǐng)求的正常處理,同時(shí)又不會(huì)阻塞主線程。


?Squirrel持久化重構(gòu)

Redis主從同步時(shí)會(huì)生成RDB。生成RDB的過(guò)程會(huì)調(diào)用Fork產(chǎn)生一個(gè)子進(jìn)程去寫(xiě)數(shù)據(jù)到硬盤(pán),F(xiàn)ork雖然有操作系統(tǒng)的COW機(jī)制,但是當(dāng)內(nèi)存用量達(dá)到10 G或20 G時(shí),依然會(huì)造成整個(gè)進(jìn)程接近秒級(jí)的阻塞。這對(duì)在線業(yè)務(wù)來(lái)說(shuō)幾乎是無(wú)法接受的。我們也會(huì)為數(shù)據(jù)可靠性要求高的業(yè)務(wù)去開(kāi)啟AOF,而開(kāi)AOF就可能因IO抖動(dòng)造成進(jìn)程阻塞,這也會(huì)影響請(qǐng)求成功率。對(duì)官方持久化機(jī)制的這兩個(gè)問(wèn)題,我們的解決方案是重構(gòu)持久化機(jī)制。

上圖是最新版的Redis持久化機(jī)制,寫(xiě)請(qǐng)求會(huì)先寫(xiě)到DB里,然后寫(xiě)到內(nèi)存Backlog,跟官方一樣。同時(shí)它會(huì)把請(qǐng)求發(fā)給異步線程,異步線程負(fù)責(zé)把變更刷到硬盤(pán)的Backlog里。當(dāng)硬盤(pán)Backlog過(guò)多時(shí),我們會(huì)主動(dòng)在業(yè)務(wù)低峰期做一次RDB ,然后把RDB之前生成的 Backlog刪除。

  如果這時(shí)候我們要做主從同步,去尋找同步點(diǎn)的時(shí)候,該怎么辦?第一步還是跟官方一樣,我們會(huì)從內(nèi)存Backlog里找有沒(méi)有要求的同步點(diǎn),如果沒(méi)有,我們會(huì)去硬盤(pán)Backlog找同步點(diǎn)。由于硬盤(pán)空間很大,硬盤(pán)Backlog可以存儲(chǔ)特別多的數(shù)據(jù),所以很少會(huì)出現(xiàn)找不到同步點(diǎn)的情況。如果硬盤(pán)Backlog也沒(méi)有,我們就會(huì)觸發(fā)一次類(lèi)似于全量重傳的操作,不需要當(dāng)場(chǎng)生成RDB,它可以直接用硬盤(pán)已存的RDB及其之后的硬盤(pán)Backlog完成全量重傳。

?

?

Squirrel熱點(diǎn)Key

  普通主、從是一個(gè)正常集群中的節(jié)點(diǎn),熱點(diǎn)主、從是游離于正常集群之外的節(jié)點(diǎn)。


?  當(dāng)有請(qǐng)求進(jìn)來(lái)讀寫(xiě)普通節(jié)點(diǎn)時(shí),節(jié)點(diǎn)內(nèi)會(huì)同時(shí)做請(qǐng)求Key的統(tǒng)計(jì)。如果某個(gè)Key達(dá)到了一定的訪問(wèn)量或者帶寬的占用量,會(huì)自動(dòng)觸發(fā)流控以限制熱點(diǎn)Key訪問(wèn),防止節(jié)點(diǎn)被熱點(diǎn)請(qǐng)求打滿。同時(shí),監(jiān)控服務(wù)會(huì)周期性的去所有Redis實(shí)例上查詢統(tǒng)計(jì)到的熱點(diǎn)Key。如果有熱點(diǎn),監(jiān)控服務(wù)會(huì)把熱點(diǎn)Key所在Slot上報(bào)到遷移服務(wù)。遷移服務(wù)會(huì)把熱點(diǎn)主從節(jié)點(diǎn)加入到這個(gè)集群中,然后把熱點(diǎn)Slot遷移到這個(gè)熱點(diǎn)主從上。因?yàn)闊狳c(diǎn)主從上只有熱點(diǎn)Slot的請(qǐng)求,所以熱點(diǎn)Key的處理能力得到了大幅提升。

通過(guò)這樣的設(shè)計(jì),可做到實(shí)時(shí)的熱點(diǎn)監(jiān)控,并及時(shí)通過(guò)流控去止損;通過(guò)熱點(diǎn)遷移,能做到自動(dòng)的熱點(diǎn)隔離和快速的容量擴(kuò)充。

?

?

持久化KV Cellar架構(gòu)和實(shí)踐

跟Tair主要有兩個(gè)架構(gòu)上的不同:①OB,②ZooKeeper。

OB跟ZooKeeper的Observer是類(lèi)似的作用,提供Cellar中心節(jié)點(diǎn)元數(shù)據(jù)的查詢服務(wù)。它可以實(shí)時(shí)與中心節(jié)點(diǎn)的Master同步最新的路由表,客戶端的路由表都是從OB去拿。

好處:①把大量的業(yè)務(wù)客戶端跟集群的大腦Master做了天然的隔離,防止路由表請(qǐng)求影響集群的管理。②OB只供路由表查詢,不參與集群的管理,所以它可以進(jìn)行水平擴(kuò)展,極大地提升了我們路由表的查詢能力。

另外,引入了ZooKeeper做分布式仲裁,解決Master、Slave在網(wǎng)絡(luò)分割情況下的“腦裂”問(wèn)題,并且通過(guò)把集群的元數(shù)據(jù)存儲(chǔ)到ZooKeeper,保證了元數(shù)據(jù)的高可靠。


?Cellar節(jié)點(diǎn)容災(zāi)——Handoff機(jī)制

一個(gè)集群節(jié)點(diǎn)的宕機(jī)一般是臨時(shí)的,一個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò)抖動(dòng)也是臨時(shí)的,會(huì)很快地恢復(fù),并重新加入集群。實(shí)現(xiàn)Handoff機(jī)制來(lái)解決這種節(jié)點(diǎn)短時(shí)故障帶來(lái)的影響。

?

如果A節(jié)點(diǎn)宕機(jī)了,會(huì)觸發(fā)Handoff機(jī)制,這時(shí)中心節(jié)點(diǎn)會(huì)通知客戶端A節(jié)點(diǎn)發(fā)生了故障,讓客戶端把分片1的請(qǐng)求也打到B上。B節(jié)點(diǎn)正常處理完客戶端的讀寫(xiě)請(qǐng)求之后,還會(huì)把本應(yīng)該寫(xiě)入A節(jié)點(diǎn)的分片1&2數(shù)據(jù)寫(xiě)入到本地的 Log 中。

如果A節(jié)點(diǎn)宕機(jī)后 3~5 分鐘,或者網(wǎng)絡(luò)抖動(dòng)30~50秒之后恢復(fù)了,A節(jié)點(diǎn)就會(huì)上報(bào)心跳到中心節(jié)點(diǎn),中心節(jié)點(diǎn)就會(huì)通知B節(jié)點(diǎn):“A節(jié)點(diǎn)恢復(fù)了,把它不在期間的數(shù)據(jù)傳給它?!边@時(shí)B節(jié)點(diǎn)就會(huì)把本地存儲(chǔ)的Log回寫(xiě)到A節(jié)點(diǎn)上。等到A節(jié)點(diǎn)擁有了故障期間的全量數(shù)據(jù)之后,中心節(jié)點(diǎn)就會(huì)告訴客戶端,A 節(jié)點(diǎn)已經(jīng)徹底恢復(fù)了,客戶端就可以重新把分片1的請(qǐng)求打回A節(jié)點(diǎn)。

通過(guò)這樣的操作,可做到秒級(jí)的快速節(jié)點(diǎn)摘除,且節(jié)點(diǎn)恢復(fù)后加回,只需補(bǔ)齊少量的增量數(shù)據(jù)。另外如果A節(jié)點(diǎn)要做升級(jí),中心節(jié)點(diǎn)先通過(guò)主動(dòng)Handoff把A節(jié)點(diǎn)流量切到B節(jié)點(diǎn),A 升級(jí)后再回寫(xiě)增量Log,然后切回流量加入集群。這樣主動(dòng)觸發(fā)Handoff機(jī)制,就實(shí)現(xiàn)了靜默升級(jí)的功能。

Cellar跨地域容災(zāi)

客戶端的寫(xiě)操作到了北京的主集群A節(jié)點(diǎn),A節(jié)點(diǎn)會(huì)像正常集群內(nèi)復(fù)制一樣,把寫(xiě)操作復(fù)制到B、D節(jié)點(diǎn)上。同時(shí)把數(shù)據(jù)復(fù)制一份到從集群的H節(jié)點(diǎn)。H節(jié)點(diǎn)處理完集群間復(fù)制寫(xiě)入之后,也會(huì)做從集群內(nèi)的復(fù)制,把寫(xiě)操作復(fù)制到從集群的I、K節(jié)點(diǎn)上。通過(guò)在主從集群的節(jié)點(diǎn)間建立一個(gè)復(fù)制鏈路,完成了集群間的數(shù)據(jù)復(fù)制,保證了最低的跨地域帶寬占用。同樣,集群間的兩個(gè)節(jié)點(diǎn)通過(guò)配置兩個(gè)雙向復(fù)制的鏈路,就可以達(dá)到雙向同步異地多活的效果。

Cellar強(qiáng)一致——Multi Raft實(shí)現(xiàn)

  強(qiáng)一致存儲(chǔ)。之前的數(shù)據(jù)復(fù)制是異步的,在做故障摘除時(shí),可能因?yàn)楣收瞎?jié)點(diǎn)數(shù)據(jù)還沒(méi)復(fù)制出來(lái),導(dǎo)致數(shù)據(jù)丟失。目前業(yè)界主流的解決方案是基于Paxos或Raft協(xié)議的強(qiáng)一致復(fù)制。我們最終選擇Raft協(xié)議。因?yàn)镽aft論文非常詳實(shí),業(yè)界也有不少比較成熟的Raft開(kāi)源實(shí)現(xiàn)。

下圖是現(xiàn)在Cellar集群Raft復(fù)制模式下的架構(gòu)圖,中心節(jié)點(diǎn)會(huì)做Raft組的調(diào)度,它會(huì)決定每一個(gè)Slot的三副本存在哪些節(jié)點(diǎn)上。


?Slot 1在存儲(chǔ)節(jié)點(diǎn) 1、2、4 上,Slot 2在存儲(chǔ)節(jié)點(diǎn)2、3、4上。每個(gè)Slot組成一個(gè)Raft 組,客戶端會(huì)去Raft Leader上進(jìn)行讀寫(xiě)。由于我們是預(yù)分配了16384 個(gè)Slot,所以在集群規(guī)模很小的時(shí)候,存儲(chǔ)節(jié)點(diǎn)上可能會(huì)有數(shù)百甚至上千個(gè)Slot。

這時(shí)如果每個(gè)Raft復(fù)制組都有自己的復(fù)制線程、 復(fù)制請(qǐng)求和Log等,資源消耗會(huì)非常大,寫(xiě)入性能會(huì)很差。所以我們做了Multi Raft實(shí)現(xiàn)。

Cellar會(huì)把同一個(gè)節(jié)點(diǎn)上所有的Raft復(fù)制組寫(xiě)一份Log,用同一組線程去做復(fù)制,不同 Raft組間的復(fù)制包也會(huì)按照目標(biāo)節(jié)點(diǎn)做整合,以保證寫(xiě)入性能不會(huì)因Raft組過(guò)多而變差。Raft內(nèi)部有自己的選主機(jī)制,它可以控制自己的主節(jié)點(diǎn),如果有任何節(jié)點(diǎn)宕機(jī),它可以通過(guò)選舉機(jī)制選出新的主節(jié)點(diǎn)。

那么,中心節(jié)點(diǎn)是不是就不需要管理Raft組了?不是的。

如果一個(gè)集群的部分節(jié)點(diǎn)經(jīng)過(guò)幾輪宕機(jī)恢復(fù)的過(guò)程,Raft Leader在存儲(chǔ)節(jié)點(diǎn)之間會(huì)變得極其不均。而為了保證數(shù)據(jù)的強(qiáng)一致,客戶端的讀寫(xiě)流量又必須發(fā)到Raft Leader,這時(shí)集群的節(jié)點(diǎn)流量會(huì)很不均衡。所以我們的中心節(jié)點(diǎn)還會(huì)做Raft組的Leader調(diào)度。

比如說(shuō)Slot 1存儲(chǔ)在節(jié)點(diǎn) 1、2、4,并且節(jié)點(diǎn)1是Leader。如果節(jié)點(diǎn)1掛了,Raft把節(jié)點(diǎn)2選成了Leader。然后節(jié)點(diǎn)1恢復(fù)了并重新加入集群,中心節(jié)點(diǎn)這時(shí)會(huì)讓節(jié)點(diǎn)2把Leader 還給節(jié)點(diǎn)1 。這樣,經(jīng)過(guò)一系列宕機(jī)和恢復(fù),存儲(chǔ)節(jié)點(diǎn)間的Leader數(shù)目仍能保證是均衡的。

?

?

  

Cellar 如何保證它的端到端高成功率?

Cellar 遇到的數(shù)據(jù)遷移和熱點(diǎn)Key問(wèn)題與Squirrel是一樣的,但解決方案不一樣。

因?yàn)镃ellar走的是自研路徑,不用考慮與官方版本的兼容性,對(duì)架構(gòu)改動(dòng)更大些。另一個(gè)問(wèn)題是慢請(qǐng)求阻塞服務(wù)隊(duì)列導(dǎo)致大面積超時(shí),這是Cellar網(wǎng)絡(luò)、工作多線程模型設(shè)計(jì)下會(huì)遇到的不同問(wèn)題。

?

Cellar智能遷移  

上圖是Cellar智能遷移架構(gòu)圖。把桶的遷移分成了三個(gè)狀態(tài)。

第一個(gè)狀態(tài)就是正常的狀態(tài),沒(méi)有任何遷移。

如果這時(shí)候要把Slot 2從A節(jié)點(diǎn)遷移到B節(jié)點(diǎn),A會(huì)給Slot 2打一個(gè)快照,然后把這個(gè)快照全量發(fā)到B節(jié)點(diǎn)上。在遷移數(shù)據(jù)的時(shí)候, B節(jié)點(diǎn)的回包會(huì)帶回B節(jié)點(diǎn)的狀態(tài)。B的狀態(tài)包括什么?引擎的壓力、網(wǎng)卡流量、隊(duì)列長(zhǎng)度等。A節(jié)點(diǎn)會(huì)根據(jù)B節(jié)點(diǎn)的狀態(tài)調(diào)整自己的遷移速度。像Squirrel一樣,它經(jīng)過(guò)一段時(shí)間調(diào)整后,遷移速度會(huì)達(dá)到一個(gè)動(dòng)態(tài)平衡,達(dá)到最快速的遷移,同時(shí)又盡可能小地影響業(yè)務(wù)的正常請(qǐng)求。

  當(dāng)Slot 2遷移完后, 會(huì)進(jìn)入圖中Slot 3的狀態(tài)??蛻舳诉@時(shí)可能還沒(méi)更新路由表,當(dāng)它請(qǐng)求到了A節(jié)點(diǎn),A節(jié)點(diǎn)會(huì)發(fā)現(xiàn)客戶端請(qǐng)求錯(cuò)了節(jié)點(diǎn),但它不會(huì)返回錯(cuò)誤,它會(huì)把請(qǐng)求代理到B節(jié)點(diǎn)上,然后把B的響應(yīng)包再返回客戶端。同時(shí)它會(huì)告訴客戶端,需要更新一下路由表了,此后客戶端就能直接訪問(wèn)到B節(jié)點(diǎn)。這樣就解決了客戶端路由更新延遲造成的請(qǐng)求錯(cuò)誤。

?

Cellar快慢列隊(duì)

  下圖上方是一個(gè)標(biāo)準(zhǔn)的線程隊(duì)列模型。網(wǎng)絡(luò)線程池接收網(wǎng)絡(luò)流量解析出請(qǐng)求包,然后把請(qǐng)求放到工作隊(duì)列里,工作線程池會(huì)從工作隊(duì)列取請(qǐng)求來(lái)處理,然后把響應(yīng)包放回網(wǎng)絡(luò)線程池發(fā)出。

我們分析線上發(fā)生的超時(shí)案例時(shí)發(fā)現(xiàn),一批超時(shí)請(qǐng)求當(dāng)中往往只有一兩個(gè)請(qǐng)求是引擎處理慢導(dǎo)致的,大部分請(qǐng)求,只是因?yàn)樵陉?duì)列等待過(guò)久導(dǎo)致整體響應(yīng)時(shí)間過(guò)長(zhǎng)而超時(shí)了。從線上分析來(lái)看,真正的慢請(qǐng)求占超時(shí)請(qǐng)求的比例只有1/20。

如何解決?很簡(jiǎn)單,拆線程池、拆隊(duì)列。

網(wǎng)絡(luò)線程在收到包之后,會(huì)根據(jù)它的請(qǐng)求特點(diǎn),是讀還是寫(xiě),快還是慢,分到四個(gè)隊(duì)列里。根據(jù)請(qǐng)求的Key個(gè)數(shù)、Value大小、數(shù)據(jù)結(jié)構(gòu)元素?cái)?shù)等對(duì)請(qǐng)求進(jìn)行快慢區(qū)分。然后用對(duì)應(yīng)的四個(gè)工作線程池處理對(duì)應(yīng)隊(duì)列的請(qǐng)求,就實(shí)現(xiàn)了快慢讀寫(xiě)請(qǐng)求的隔離。

不過(guò)也帶來(lái)一個(gè)問(wèn)題,線程池從一個(gè)變成四個(gè),那線程數(shù)是不是變成原來(lái)的四倍?其實(shí)并不是的,某個(gè)線程池空閑的時(shí)候會(huì)去幫助其它的線程池處理請(qǐng)求。所以,線程池變成了四個(gè),但線程總數(shù)并沒(méi)有變。線上驗(yàn)證這樣能把服務(wù)TP999的延遲降低86%,大幅降低超時(shí)率。

?

Cellar熱點(diǎn)Key

上圖是Cellar熱點(diǎn)Key解決方案的架構(gòu)圖。

中心節(jié)點(diǎn)加了熱點(diǎn)區(qū)域管理,圖示這個(gè)集群在節(jié)點(diǎn)C、D放了熱點(diǎn)區(qū)域。

如果客戶端有一個(gè)寫(xiě)操作到了A節(jié)點(diǎn),A節(jié)點(diǎn)處理完成后,會(huì)根據(jù)實(shí)時(shí)的熱點(diǎn)統(tǒng)計(jì)結(jié)果判斷寫(xiě)入的Key是否為熱點(diǎn)。

如果是一個(gè)熱點(diǎn),那么它會(huì)在做集群內(nèi)復(fù)制的同時(shí),還會(huì)把這個(gè)數(shù)據(jù)復(fù)制有熱點(diǎn)區(qū)域的節(jié)點(diǎn)(C、D)。同時(shí),存儲(chǔ)節(jié)點(diǎn)在返回結(jié)果給客戶端時(shí),會(huì)告訴客戶端這個(gè)Key是熱點(diǎn),這時(shí)客戶端內(nèi)會(huì)緩存這個(gè)熱點(diǎn)Key。當(dāng)客戶端有這個(gè)Key的讀請(qǐng)求時(shí),它就會(huì)直接去熱點(diǎn)區(qū)域做數(shù)據(jù)的讀取。

通過(guò)這樣的方式,可以做到只對(duì)熱點(diǎn)數(shù)據(jù)做擴(kuò)容,不像Squirrel,要把整個(gè)Slot遷出來(lái)做擴(kuò)容。有必要的話,中心節(jié)點(diǎn)也可以把熱點(diǎn)區(qū)域放到集群的所有節(jié)點(diǎn)上,所有的熱點(diǎn)讀請(qǐng)求就能均衡的分到所有節(jié)點(diǎn)上。另外,通過(guò)這種實(shí)時(shí)的熱點(diǎn)數(shù)據(jù)復(fù)制,我們很好地解決了類(lèi)似客戶端緩存熱點(diǎn)KV方案造成的一致性問(wèn)題。

?

?

發(fā)展規(guī)劃和業(yè)界趨勢(shì)

  按照服務(wù)、系統(tǒng)、硬件三層來(lái)進(jìn)行闡述。首先在服務(wù)層,主要有三點(diǎn):

 ?、賀edis Gossip協(xié)議優(yōu)化。Gossip協(xié)議在集群的規(guī)模變大之后,消息量會(huì)劇增,F(xiàn)ailover時(shí)間也會(huì)變得越來(lái)越長(zhǎng)。當(dāng)集群規(guī)模達(dá)到TB級(jí)后,可用性會(huì)受到很大的影響,需優(yōu)化。

②已經(jīng)在Cellar存儲(chǔ)節(jié)點(diǎn)的數(shù)據(jù)副本間做了Raft復(fù)制,可以保證數(shù)據(jù)強(qiáng)一致,后面會(huì)在Cellar的中心點(diǎn)內(nèi)部也做一個(gè)Raft復(fù)制,這樣就不用依賴于ZooKeeper做分布式仲裁、元數(shù)據(jù)存儲(chǔ)了,架構(gòu)也會(huì)變得更加簡(jiǎn)單、可靠。

③Squirrel和Cellar是基于不同的開(kāi)源項(xiàng)目研發(fā)的,所以API和訪問(wèn)協(xié)議不同,之后會(huì)考慮將Squirrel和Cellar在SDK層做整合,雖然后端會(huì)有不同的存儲(chǔ)集群,但業(yè)務(wù)側(cè)可以用一套SDK進(jìn)行訪問(wèn)。

?

  在系統(tǒng)層面,正在調(diào)研并去落地一些Kernel Bypass技術(shù),像DPDK、SPDK這種網(wǎng)絡(luò)和硬盤(pán)的用戶態(tài)IO技術(shù)。它可以繞過(guò)內(nèi)核,通過(guò)輪詢機(jī)制訪問(wèn)這些設(shè)備,可以極大提升系統(tǒng)的IO能力。存儲(chǔ)作為IO密集型服務(wù),性能會(huì)獲得大幅的提升。

  在硬件層面,像支持RDMA的智能網(wǎng)卡能大幅降低網(wǎng)絡(luò)延遲和提升吞吐;還有像3D XPoint這樣的閃存技術(shù),比如英特爾新發(fā)布的AEP存儲(chǔ),其訪問(wèn)延遲已經(jīng)比較接近內(nèi)存了,以后閃存跟內(nèi)存之間的界限也會(huì)變得越來(lái)越模糊;計(jì)算型硬件,比如通過(guò)在閃存上加FPGA 卡,把原本應(yīng)該CPU做的工作,像數(shù)據(jù)壓縮、解壓等,下沉到卡上執(zhí)行,這種硬件能在解放CPU的同時(shí),也可以降低服務(wù)的響應(yīng)延遲。

?


KV存儲(chǔ)(Squirrel、Cellar架構(gòu))的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
喀喇沁旗| 鹿邑县| 南昌县| 眉山市| 云南省| 长乐市| 宝兴县| 嘉定区| 友谊县| 苗栗市| 剑川县| 舟曲县| 会泽县| 临海市| 沅陵县| 苗栗市| 上饶市| 开江县| 保山市| 平原县| 阳山县| 平谷区| 吉木乃县| 上饶市| 梁平县| 旅游| 鲜城| 宁陵县| 邯郸市| 镇沅| 双牌县| 阳新县| 南溪县| 阜新| 湖南省| 喀什市| 昭通市| 始兴县| 东丰县| 阿图什市| 深州市|