騰訊Tendis 能干掉 Redis ?你繼續(xù)吹牛吧 !

來(lái)源:jingjunli,騰訊 IEG 后臺(tái)開(kāi)發(fā)工程師
Redis 作為高性能緩存被廣泛應(yīng)用到各個(gè)業(yè)務(wù), 比如游戲的排行榜, 分布式鎖等場(chǎng)景。
經(jīng)過(guò)在 IEG 的長(zhǎng)期運(yùn)營(yíng), 我們也遇到 Redis 一些痛點(diǎn)問(wèn)題, 比如內(nèi)存占用高, 數(shù)據(jù)可靠性差, 業(yè)務(wù)維護(hù)緩存和存儲(chǔ)的一致性繁瑣。
由 騰訊互娛 CROS DBA 團(tuán)隊(duì) & 騰訊云數(shù)據(jù)庫(kù)團(tuán)隊(duì)聯(lián)合研發(fā)的 Tendis 推出了: 緩存版 、 混合存儲(chǔ)版 和 存儲(chǔ)版 三種不同產(chǎn)品形態(tài), 針對(duì)不同的業(yè)務(wù)需求, 本文主要介紹 混合存儲(chǔ)版 的整體架構(gòu), 并且詳細(xì)揭秘內(nèi)部的原理。
導(dǎo)語(yǔ)
本文首先介紹騰訊 IEG 運(yùn)營(yíng) Redis 遇到的一些痛點(diǎn)問(wèn)題, 然后介紹由 騰訊互娛 CROS DBA 團(tuán)隊(duì) & 騰訊云數(shù)據(jù)庫(kù)團(tuán)隊(duì)聯(lián)合研發(fā)的 Tendis 的三種不同的產(chǎn)品形態(tài)。最后重點(diǎn)介紹冷熱混合存儲(chǔ)版的架構(gòu), 并且重點(diǎn)介紹各個(gè)組件的功能特性。
背景介紹
Redis 有哪些痛點(diǎn) ?
在使用的過(guò)程中, 主要遇到以下一些痛點(diǎn)問(wèn)題:
內(nèi)存成本高
業(yè)務(wù)不同階段對(duì) QPS 要求不同 比如游戲業(yè)務(wù), 剛上線的新游戲特別火爆, 為了支持上千萬(wàn)同時(shí)在線, 需要不斷的進(jìn)行擴(kuò)容增加機(jī)器。運(yùn)營(yíng)一段時(shí)間后, 游戲玩家可能變少, 訪問(wèn)頻率(QPS)沒(méi)那么高, 依然占用大量機(jī)器, 維護(hù)成本很高。 需要為 Fork 預(yù)留內(nèi)存 Redis 保存全量數(shù)據(jù)時(shí), 需要 Fork 一個(gè)進(jìn)程。Linux 的 fork 系統(tǒng)調(diào)用基于 Copy On Write 機(jī)制, 如果在此期間 Redis 有大量的寫(xiě)操作, 父子進(jìn)程就需要各自維護(hù)一份內(nèi)存。因此部署 Redis 的機(jī)器往往需要預(yù)留一半的內(nèi)存。 緩存一致性的問(wèn)題 對(duì)于 Redis + MySQL 的架構(gòu)需要業(yè)務(wù)方花費(fèi)大量的精力來(lái)維護(hù)緩存和數(shù)據(jù)庫(kù)的一致性。
數(shù)據(jù)可靠性 Redis 本質(zhì)上是一個(gè)內(nèi)存數(shù)據(jù)庫(kù), 用戶雖然可以使用 AOF 的 Always 來(lái)落盤(pán)保證數(shù)據(jù)可靠性, 但是會(huì)帶來(lái)性能的大幅下降, 因此生產(chǎn)環(huán)境很少有使用。另外 不支持 回檔, Master 故障后, 異步復(fù)制會(huì)造成數(shù)據(jù)的丟失。
異步復(fù)制 Redis 主備使用異步復(fù)制, 這個(gè)是異步復(fù)制固有的問(wèn)題。主備使用異步復(fù)制, 響應(yīng)延遲低, 性能高, 但是 Master 故障后, 會(huì)造成數(shù)據(jù)丟失。
Tendis 是什么 ?
Tendis 是集騰訊眾多海量 KV 存儲(chǔ)優(yōu)勢(shì)于一身的 Redis 存儲(chǔ)解決方案, 并 100% 兼容 Redis 協(xié)議和 Redis4.0 所有數(shù)據(jù)模型。作為一個(gè)高可用、高性能的分布式 KV 存儲(chǔ)數(shù)據(jù)庫(kù), 從訪問(wèn)時(shí)延、持久化需求、整體成本等不同維度的考量, Tendis 推出了 緩存版 、 混合存儲(chǔ)版和 存儲(chǔ)版 三種不同產(chǎn)品形態(tài),并將存儲(chǔ)版開(kāi)源。感興趣的小伙伴 可以去 Github 關(guān)注我們的項(xiàng)目: Tencent/Tendis

Tendis 緩存版 適用于對(duì)延遲要求特別敏感, 并且對(duì) QPS 要求很高的業(yè)務(wù)。基于社區(qū) Redis 4.0 版本進(jìn)行定制開(kāi)發(fā)。
Tendis 存儲(chǔ)版 適用于大容量, 延遲不敏感型業(yè)務(wù), 數(shù)據(jù)全部存儲(chǔ)在 磁盤(pán), 適合溫冷數(shù)據(jù)的存儲(chǔ)。Tendis 存儲(chǔ)版是騰訊互娛 CROS DBA 團(tuán)隊(duì) & 騰訊云數(shù)據(jù)庫(kù)團(tuán)隊(duì) 自主設(shè)計(jì)和研發(fā)的開(kāi)源分布式高性能 KV 存儲(chǔ)系統(tǒng)。另外在 可靠性、復(fù)制機(jī)制、并發(fā)控制、gossip 實(shí)現(xiàn)以及數(shù)據(jù)搬遷等做了大量的優(yōu)化, 并且解決了一些 Redis cluster 比較棘手的問(wèn)題。完全兼容 Redis 協(xié)議, 并使用 RocksDB 作為底層存儲(chǔ)引擎。
Tendis 冷熱混合存儲(chǔ)版 冷熱混合存儲(chǔ) 綜合了緩存版和存儲(chǔ)版的優(yōu)點(diǎn), 緩存層存放熱數(shù)據(jù), 全量數(shù)據(jù)存放在存儲(chǔ)層。這既保證了熱數(shù)據(jù)的訪問(wèn)性能,同時(shí)保證了全量數(shù)據(jù)的可靠性,同時(shí)熱數(shù)據(jù)支持自動(dòng)降冷。
Tendis 冷熱混合存儲(chǔ)版 整體架構(gòu)
Tendis 冷熱混合存儲(chǔ)版主要由 Proxy 、緩存層 Redis 、 存儲(chǔ)層 Tendis 存儲(chǔ)版 和 同步層 Redis-sync 組成, 其中每個(gè)組件的功能如下:
Proxy 組件 : 負(fù)責(zé)對(duì)客戶端請(qǐng)求進(jìn)行路由分發(fā),將不同的 Key 的命令分發(fā)到正確的分片,同時(shí) Proxy 還負(fù)責(zé)了部分監(jiān)控?cái)?shù)據(jù)的采集,以及高危命令在線禁用等功能。
緩存層 Redis Cluster : 緩存層 Redis 基于 社區(qū) Redis 4.0 進(jìn)行開(kāi)發(fā)。Redis 具有以下功能: 1) 版本控制 2) 自動(dòng)將 冷數(shù)據(jù)從緩存層中淘汰, 將熱數(shù)據(jù)從存儲(chǔ)層加載到緩存層; 3) 使用 Cuckoo Filter 表示全量 Keys, 防止緩存穿透; 4) 基于 RDB+AOF 擴(kuò)縮容方式, 擴(kuò)縮容更加高效便捷。
存儲(chǔ)層 Tendis Cluster : Tendis 存儲(chǔ)版 是騰訊基于 RocksDB 自研的 兼容 Redis 協(xié)議的 KV 存儲(chǔ)引擎, 該引擎已經(jīng)在騰訊集團(tuán)內(nèi)部運(yùn)營(yíng)多年, 性能和穩(wěn)定性得到了充分的驗(yàn)證。在混合存儲(chǔ)系統(tǒng)中主要負(fù)責(zé)全量數(shù)據(jù)的存儲(chǔ)和讀取, 以及數(shù)據(jù)備份, 增量日志備份等功能。
同步層 Redis-sync : 1) 并行數(shù)據(jù)導(dǎo)入 存儲(chǔ)層 Tendis; 2) 服務(wù)無(wú)狀態(tài), 故障重新拉起; 3) 數(shù)據(jù)自動(dòng)路由。

Tendis 冷熱混合存儲(chǔ)的一些重要特性介紹:
緩存層 Redis Cluster和存儲(chǔ)層 Tendis Cluster分別進(jìn)行擴(kuò)縮容, 集群自治管理等。冷數(shù)據(jù)自動(dòng)降冷, 降低內(nèi)存成本; 熱數(shù)據(jù)自動(dòng)緩存, 降低訪問(wèn)延遲
緩存層 Redis Cluster
冷熱混合存儲(chǔ)緩存層 Redis 在社區(qū)版的基礎(chǔ)上增加了以下功能:
版本控制 冷熱數(shù)據(jù)交互 Cuckoo Filter 避免緩存穿透 智能淘汰算法 基于 RDB+AOF 擴(kuò)縮容
下面分別對(duì)這幾個(gè)特性進(jìn)行詳細(xì)的講解。
版本控制
首先基于社區(qū)版 Redis 改動(dòng)是版本控制。我們?yōu)槊總€(gè) Key 和 每條 Aof 增加一個(gè) Version , 并且 Version 是單調(diào)遞增的。在每次更新/新增一個(gè) Key 后, 將當(dāng)前節(jié)點(diǎn)的 Version 賦值給 Key 和 Value, 然后對(duì)全局的 Version++; 如下所示, 在 redisObject 中添加 64bits, 其中 48bits 用于版本控制。
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount;
/* for hybrid storage */
unsigned flag:4; /* OBJ_FLAG_... */
unsigned reserved:4;
unsigned counter:8; /* for cold-data-cache-policy */
unsigned long long revision:REVISION_BITS; /* for value version */
void *ptr;
} robj;
引入版本控制主要帶來(lái)以下優(yōu)勢(shì):
增量 RDB
社區(qū)版 Redis 主備在斷線重連后, 如果 slave 發(fā)送的 psync_offset 對(duì)應(yīng)的數(shù)據(jù)不在當(dāng)前的 Master 的 repl_backlog 中, 則主備需要重新進(jìn)行全量同步。再引入 Version 之后, slave 斷線重連, 給 Master 發(fā)送 帶 Version 的
PSYNC replid psync_offset version命令。如果出現(xiàn)上述情況, Master 將大于等于 Version 的數(shù)據(jù)生成增量 RDB, 發(fā)給 Slave, 進(jìn)而解決需要增量, 同步比較慢的問(wèn)題。
Aof 的冪等
如果同步層 Redis-sync 出現(xiàn)網(wǎng)絡(luò)瞬斷(短暫的和緩存層或者存儲(chǔ)層斷開(kāi)), 作為一個(gè)無(wú)狀態(tài)的同步組件, Redis-sync 會(huì)重新拉取未同步到 Tendis 的增量數(shù)據(jù), 重新發(fā)送給 Tendis。每條 Aof 都具有一個(gè) Version, Tendis 在執(zhí)行的時(shí)候僅會(huì)執(zhí)行比當(dāng)前 Version 大的 Aof, 避免 aof 執(zhí)行多次導(dǎo)致的數(shù)據(jù)不一致。
冷熱數(shù)據(jù)交互
冷數(shù)據(jù)的恢復(fù)指當(dāng)用戶訪問(wèn)的 Key 不在緩存層, 需要將數(shù)據(jù)從存儲(chǔ)層重新加載到緩存層。數(shù)據(jù)恢復(fù)這里是緩存層直接和存儲(chǔ)層直接交互, 當(dāng)冷 Keys 訪問(wèn)的請(qǐng)求比較大, 數(shù)據(jù)恢復(fù)很容易成為瓶頸, 因此為每個(gè) Tendis 節(jié)點(diǎn)建立一個(gè)連接池, 專門(mén)負(fù)責(zé)與這個(gè) Tendis 節(jié)點(diǎn)進(jìn)行冷熱數(shù)據(jù)恢復(fù)。

用戶訪問(wèn)一個(gè) Key 的具體流程如下:
首先判斷 Key 是否在緩存層, 如果緩存層存在, 則執(zhí)行命令; 如果緩存層不存在, 查詢 Cuckoo Filter, 判斷 Key 是否有可能在存儲(chǔ)層; 如果 Key 可能在存儲(chǔ)層, 則向存儲(chǔ)層發(fā)送 dumpx dbid key withttl命令嘗試從存儲(chǔ)層獲取數(shù)據(jù), 并且阻塞當(dāng)前請(qǐng)求的客戶端;存儲(chǔ)層收到 dumpx , 如果 Key 在存儲(chǔ)層, 則向緩存層返回 RESTOREEX dbid key ttl value; 如果 Key 不在存儲(chǔ)層(Cuckoo Filter 的誤判), 則向緩存層返回DUMPXERROR key;存儲(chǔ)層收到 RESTOREEX 或者 DUMPXERROR 后, 將冷數(shù)據(jù)恢復(fù)。然后就可以喚醒阻塞的客戶端, 執(zhí)行客戶端的請(qǐng)求。
Key 降冷 與 Cuckoo Filter
這里主要講解混合存儲(chǔ)從 1:1 版的緩存層緩存全量 Keys, 到 N:M 版的緩存層將 Key 和 Value 同時(shí)驅(qū)逐的演進(jìn), 以及我們引入 Cuckoo Filter 避免緩存穿透, 同時(shí)節(jié)省大量?jī)?nèi)存。
Key 降冷的背景介紹 2020 年 6 月份上線的 1:1 版的冷熱混合存儲(chǔ), 緩存層 Redis 存儲(chǔ)全量的 Keys 和熱 Values(All Keys + Hot values ), 存儲(chǔ)層 Tendis 存儲(chǔ)全量的 Keys 和 Values(All Keys + All values )。在上線運(yùn)行了一段時(shí)間后, 發(fā)現(xiàn)全量 Keys 的內(nèi)存開(kāi)銷特別大, 冷熱混合的收益并不明顯。為了進(jìn)一步釋放內(nèi)存空間, 提高緩存的效率, 我們放棄了 Redis 緩存全量 Keys 的方案, 驅(qū)逐的時(shí)候?qū)?key 和 Value 都從緩存層淘汰。 Cuckoo Filter 解決緩存擊穿和緩存穿透 如果緩存層不存儲(chǔ)全量的 Keys, 就會(huì)出現(xiàn)緩存擊穿和緩存穿透的問(wèn)題。為了解決這一問(wèn)題, 緩存層引入 Cuckoo Filter 表示全量的 keys 。我們需要一個(gè)支持刪除、可動(dòng)態(tài)伸縮并且空間利用率高的 Membership Query 結(jié)構(gòu), 經(jīng)過(guò)我們的調(diào)研和對(duì)比分析, 最終選擇 Dynamic Cuckoo Filter。Dynamic Cuckoo Filter 實(shí)現(xiàn) 項(xiàng)目初期參考了 RedisBloom 中 Cuckoo Filter 的實(shí)現(xiàn), 在開(kāi)發(fā)的過(guò)程中也遇到了一些坑, RedisBloom 實(shí)現(xiàn)的 Cuckoo Filter 在刪除的時(shí)候會(huì)出現(xiàn)誤刪, 最終給 RedisBloom 提 PR(Fix Cuckoo filter compact cause deleted by mistake #260 ) 修復(fù)了問(wèn)題。 Key 降冷的收益 最終采用將 Key 和 Value 同時(shí)從緩存層淘汰, 降低內(nèi)存的收益很大。比如現(xiàn)網(wǎng)的一個(gè)業(yè)務(wù), 總共有 6620 W 個(gè) Keys , 在緩存全量 Keys 的時(shí)候 占用 18408 MB 的內(nèi)存, 在 Key 降冷后 僅僅占用 593MB 。
智能淘汰/加載策略
作為冷熱混合存儲(chǔ)系統(tǒng), 熱數(shù)據(jù)在緩存層, 全量數(shù)據(jù)在存儲(chǔ)層。關(guān)鍵的問(wèn)題是淘汰和加載策略, 這里直接影響緩存的效率, 細(xì)分主要有兩點(diǎn): 1) 當(dāng)緩存層內(nèi)存滿時(shí), 選擇哪些數(shù)據(jù)淘汰; 2) 當(dāng)用戶訪問(wèn)存儲(chǔ)層的數(shù)據(jù)時(shí), 是否需要將其放入緩存層 。
首先介紹混合存儲(chǔ)的淘汰策略, 主要有以下兩個(gè)淘汰策略:
maxmemory-policy 當(dāng)緩存層 Redis 內(nèi)存使用到達(dá) maxmemory, 系統(tǒng)將按照 maxmemory-policy 的內(nèi)存策略將 Key/Value 從緩存層驅(qū)逐, 釋放內(nèi)存空間。(驅(qū)逐是指將 Key/Value 從緩存層中淘汰掉, 存儲(chǔ)層 和 緩存層的 Cuckoo Filter 依然存在該 Key; ) value-eviction-policy 如果配置 value-eviction-policy, 后臺(tái)會(huì)定期將用戶 N 天未訪問(wèn)的 Key/Value 被驅(qū)逐出內(nèi)存;
緩存加載策略 為了避免緩存污染的問(wèn)題(比如類似 Scan 的訪問(wèn), 遍歷存儲(chǔ)層的數(shù)據(jù), 將緩存層真正的熱數(shù)據(jù)淘汰, 從而造成了緩存效率低下) 。我們實(shí)現(xiàn)緩存加載策略: 僅僅將規(guī)定時(shí)間內(nèi)訪問(wèn)頻率超過(guò)某個(gè)閾值的數(shù)據(jù)加載到緩存中, 這里的時(shí)間和閾值都是可配置的。
基于 RDB+AOF 擴(kuò)縮容
社區(qū)版 Redis 的擴(kuò)容流程:

社區(qū)版 Redis 擴(kuò)容存在的一些問(wèn)題:
importing 和 migrating 的設(shè)置不是原子的
先設(shè)置目標(biāo)節(jié)點(diǎn) slot 為 importing 狀態(tài), 再設(shè)置源節(jié)點(diǎn)的 slot 為 migrating 狀態(tài)。如果反過(guò)來(lái), 由于兩次操作非原子: 源節(jié)點(diǎn)設(shè)置為 migrating , 目標(biāo)節(jié)點(diǎn)還未設(shè)置 migrating 狀態(tài), 請(qǐng)求在這兩個(gè)節(jié)點(diǎn)間反復(fù) Move 。
搬遷以 Key 為粒度, 效率較低
Migrate 命令每次搬遷一個(gè)或者多個(gè) Keys, 將整個(gè) Slot 搬遷到目標(biāo)節(jié)點(diǎn)需要多次網(wǎng)絡(luò)交互。
大 Key 問(wèn)題
由于 Migrate 命令是同步命令, 在搬遷過(guò)程中是不能處理其他用戶請(qǐng)求的, 因此可能會(huì)影響業(yè)務(wù)。(延遲時(shí)間波動(dòng)較大)
由于社區(qū)版 Redis 存在的上述問(wèn)題, 我們實(shí)現(xiàn)了基于 RDB+Aof 的擴(kuò)縮容方式, 大致流程如下:
管控添加新節(jié)點(diǎn), 規(guī)劃待搬遷 slots; 管控端向目標(biāo)節(jié)點(diǎn)下發(fā) slot 同步命令: cluster slotsync beginSlot endSlot [[beginSlot endSlot]...]目標(biāo)節(jié)點(diǎn)向源節(jié)點(diǎn)發(fā)送 sync [slot ...], 命令請(qǐng)求同步 slot 數(shù)據(jù)源節(jié)點(diǎn)生成指定 slot 數(shù)據(jù)的一致性快照全量數(shù)據(jù)(RDB), 并將其發(fā)送給目標(biāo)節(jié)點(diǎn) 源節(jié)點(diǎn)開(kāi)始持續(xù)發(fā)送增量數(shù)據(jù)(Aof) 管控端定位獲取源節(jié)點(diǎn)和目標(biāo)節(jié)點(diǎn)的落后值 (diff_bytes), 如果落后值在指定的閾值內(nèi), 管控端向目標(biāo)節(jié)點(diǎn)發(fā)送 cluster slotfailover(流程類似 Redis 的 cluster failover, 首先阻塞源節(jié)點(diǎn)寫(xiě)入, 然后等待目標(biāo)節(jié)點(diǎn)和源節(jié)點(diǎn)的落后值為 0, 最后將 搬遷的 slots 歸屬目標(biāo)節(jié)點(diǎn))

同步層 Redis-sync
同步層 Redis-sync 模擬 Redis Slave 的行為, 接收 RDB 和 Aof, 然后并行地導(dǎo)入到存儲(chǔ)層 Tendis。同步層主要需要解決以下問(wèn)題:
并發(fā)地導(dǎo)入到存儲(chǔ)層 Tendis, 如何保證時(shí)序正確 ? 特殊命令的處理, 比如 FLUSHALL/FLUSHDB/SWAPDB/SELECT/MULTI 等 ? 作為一個(gè)無(wú)狀態(tài)的同步組件, 如何保證故障后, 數(shù)據(jù)斷點(diǎn)續(xù)傳 ? 緩存層和存儲(chǔ)層 分別進(jìn)行擴(kuò)縮容, 如何將請(qǐng)求路由到正確的 Tendis 節(jié)點(diǎn) ?

為了解決上述的三個(gè)問(wèn)題, 我們實(shí)現(xiàn)了下面的功能:
Slot 內(nèi)串行, Slot 間并行 針對(duì)問(wèn)題 1, Redis-sync 中采用與 Redis 相同的計(jì)算 Slot 的算法, 解析到具體的命令后, 根據(jù) Key 所屬的 slot, 將其放到對(duì)應(yīng)的 隊(duì)列中( slot%QueueSize )。因此同一個(gè) Slot 的數(shù)據(jù)是串行寫(xiě)入, 不同 slot 的數(shù)據(jù)可以并行寫(xiě)入, 不會(huì)出現(xiàn)時(shí)序錯(cuò)亂的行為。 串并轉(zhuǎn)換 針對(duì)問(wèn)題 2, Redis-sync 會(huì)在并行和串行模式之間進(jìn)行轉(zhuǎn)換。比如收到 FLUSHDB 命令, 這是需要將 FLUSHDB 命令 前的命令都執(zhí)行完, 再執(zhí)行 FLUSHDB 命令。 定期上報(bào) 針對(duì)問(wèn)題 3, Redis-sync 會(huì)定期將已發(fā)送給存儲(chǔ)層的 aof 的 Version 持久化到 存儲(chǔ)層。如何 Redis-sync 故障, 首先從 存儲(chǔ)層獲取上次已發(fā)送的位置, 然后向?qū)?yīng)的 Redis 節(jié)點(diǎn)發(fā)送 psync, 請(qǐng)求同步。 數(shù)據(jù)自動(dòng)路由 針對(duì)問(wèn)題 4, Redis-sync 會(huì)定期從存儲(chǔ)層獲取 Slot到Tendis 節(jié)點(diǎn)的映射關(guān)系, 并且維護(hù)這些 Tendis 節(jié)點(diǎn)的連接池。請(qǐng)求從 緩存層到達(dá), 然后計(jì)算請(qǐng)求所屬的 slot, 然后發(fā)送到正確的 Tendis 節(jié)點(diǎn)。
存儲(chǔ)層 Tendis Cluster
Tendis 是兼容 Redis 核心數(shù)據(jù)結(jié)構(gòu)與協(xié)議的分布式高性能 KV 數(shù)據(jù)庫(kù), 主要具有以下特性:
兼容 Redis 協(xié)議 完全兼容 redis 協(xié)議,支持 redis 主要數(shù)據(jù)結(jié)構(gòu)和接口,兼容大部分原生 Redis 命令。 持久化存儲(chǔ) 使用 rocksdb 作為存儲(chǔ)引擎,所有數(shù)據(jù)以特定格式存儲(chǔ)在 rocksdb 中,最大支持 PB 級(jí)存儲(chǔ)。 去中心化架構(gòu) 類似于 redis cluster 的分布式實(shí)現(xiàn),所有節(jié)點(diǎn)通過(guò) gossip 協(xié)議通訊,可指定 hashtag 來(lái)控制數(shù)據(jù)分布和訪問(wèn),使用和運(yùn)維成本極低。 水平擴(kuò)展 集群支持增刪節(jié)點(diǎn),并且數(shù)據(jù)可以按照 slot 在任意兩節(jié)點(diǎn)之間遷移,擴(kuò)容和縮容過(guò)程中對(duì)應(yīng)用運(yùn)維人員透明,支持?jǐn)U展至 1000 個(gè)節(jié)點(diǎn)。 故障自動(dòng)切換 自動(dòng)檢測(cè)故障節(jié)點(diǎn),當(dāng)故障發(fā)生后,slave 會(huì)自動(dòng)提升為 master 繼續(xù)對(duì)外提供服務(wù)。

推薦閱讀: 推薦一款神器,助你秒級(jí)定位線上問(wèn)題! 代碼中大量的if/else,你有什么優(yōu)化方案? 你還在用Jenkins?趕快看看這些替代方案吧! 程序員常用的 15 款Java開(kāi)發(fā)者工具 最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:關(guān)注公眾號(hào)并回復(fù) java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 明天見(jiàn)(??ω??)??
