騰訊云超火開源數(shù)據(jù)庫產(chǎn)品架構(gòu)揭秘

來源: 騰訊云數(shù)據(jù)庫
作者:騰訊云數(shù)據(jù)庫
時(shí)間:2021-04-15
18014
本文帶你一起回顧騰訊云數(shù)據(jù)庫Tendis混合存儲(chǔ)版的整體架構(gòu),并且詳細(xì)揭秘其內(nèi)部的原理。

Redis作為高性能緩存經(jīng)常被廣泛應(yīng)用到各個(gè)業(yè)務(wù)——如游戲的排行榜、分布式鎖等場(chǎng)景。

但Redis也并非萬能的,在長(zhǎng)期的使用過程中,我們也遇到Redis一些痛點(diǎn)問題,比如內(nèi)存占用高,數(shù)據(jù)可靠性差,業(yè)務(wù)維護(hù)緩存和存儲(chǔ)的一致性繁瑣等。

因此,騰訊云數(shù)據(jù)庫Tendis誕生了,今天,我們就一起回顧騰訊云數(shù)據(jù)庫Tendis混合存儲(chǔ)版的整體架構(gòu),并且詳細(xì)揭秘其內(nèi)部的原理。

Redis&Tendis

使用Redis有哪些痛點(diǎn)?我大致分類為以下三種:

一、內(nèi)存成本高

首先,在產(chǎn)品的不同階段,業(yè)務(wù)對(duì)QPS的要求不同,以游戲業(yè)務(wù)為例,剛上線的新游戲通常來說都特別火爆,為了支持上千萬同時(shí)在線,需要不斷的進(jìn)行擴(kuò)容增加機(jī)器。而在運(yùn)營(yíng)一段時(shí)間后,游戲玩家逐漸變少到一個(gè)正常的用戶量級(jí),訪問頻率(QPS)沒那么高,依然占用大量機(jī)器,維護(hù)成本很高。

其次,Redis保存全量數(shù)據(jù)時(shí),需要Fork一個(gè)進(jìn)程。Linux的fork系統(tǒng)調(diào)用基于Copy On Write機(jī)制,如果在此期間Redis有大量的寫操作,父子進(jìn)程就需要各自維護(hù)一份內(nèi)存。因此部署Redis的機(jī)器往往需要預(yù)留一半的內(nèi)存。

二、緩存一致性的問題

對(duì)于Redis+MySQL的架構(gòu)需要業(yè)務(wù)方花費(fèi)大量的精力來維護(hù)緩存和數(shù)據(jù)庫的一致性。

三、數(shù)據(jù)可靠性

Redis本質(zhì)上是一個(gè)內(nèi)存數(shù)據(jù)庫,用戶雖然可以使用AOF的Always來落盤保證數(shù)據(jù)可靠性,但是會(huì)帶來性能的大幅下降,因此生產(chǎn)環(huán)境很少有使用。另外不支持回檔,Master故障后,異步復(fù)制會(huì)造成數(shù)據(jù)的丟失。

四、異步復(fù)制

Redis主備使用異步復(fù)制,這個(gè)是異步復(fù)制固有的問題。主備使用異步復(fù)制,響應(yīng)延遲低,性能高,但是Master故障后,會(huì)造成數(shù)據(jù)丟失。

關(guān)于Tendis,我們已經(jīng)做了很多介紹(開源一周star上千,什么產(chǎn)品這么香?)在此不再贅述。接下來我們對(duì)Tendis混合存儲(chǔ)版的整體架構(gòu)進(jìn)行詳細(xì)的解讀。

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)行開發(fā)。Redis具有以下功能:

版本控制;自動(dòng)將冷數(shù)據(jù)從緩存層中淘汰,將熱數(shù)據(jù)從存儲(chǔ)層加載到緩存層;使用Cuckoo Filter表示全量Keys,防止緩存穿透;基于RDB+AOF擴(kuò)縮容方式,擴(kuò)縮容更加高效便捷。

三、存儲(chǔ)層Tendis Cluster

Tendis存儲(chǔ)版是騰訊基于RocksDB自研的兼容Redis協(xié)議的KV存儲(chǔ)引擎,該引擎已經(jīng)在騰訊內(nèi)部運(yùn)營(yíng)多年,性能和穩(wěn)定性得到了充分的驗(yàn)證。在混合存儲(chǔ)系統(tǒng)中主要負(fù)責(zé)全量數(shù)據(jù)的存儲(chǔ)和讀取,以及數(shù)據(jù)備份,增量日志備份等功能。

四、同步層Redis-sync

并行數(shù)據(jù)導(dǎo)入存儲(chǔ)層Tendis;服務(wù)無狀態(tài),故障重新拉起;數(shù)據(jù)自動(dòng)路由。

640.webp.jpg

Tendis冷熱混合存儲(chǔ)的一些重要特性總結(jié):

緩存層Redis Cluster和存儲(chǔ)層Tendis Cluster分別進(jìn)行擴(kuò)縮容,集群自治管理等;

冷數(shù)據(jù)自動(dòng)降冷,降低內(nèi)存成本;熱數(shù)據(jù)自動(dòng)緩存,降低訪問延遲。

緩存層Redis Cluster

一、版本控制

首先基于社區(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;

引入版本控制主要帶來以下優(yōu)勢(shì):

1.增量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)而解決需要增量,同步比較慢的問題。

2.Aof的冪等

如果同步層Redis-sync出現(xiàn)網(wǎng)絡(luò)瞬斷(短暫的和緩存層或者存儲(chǔ)層斷開),作為一個(gè)無狀態(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)用戶訪問的Key不在緩存層,需要將數(shù)據(jù)從存儲(chǔ)層重新加載到緩存層。數(shù)據(jù)恢復(fù)這里是緩存層直接和存儲(chǔ)層直接交互,當(dāng)冷Keys訪問的請(qǐng)求比較大,數(shù)據(jù)恢復(fù)很容易成為瓶頸,因此為每個(gè)Tendis節(jié)點(diǎn)建立一個(gè)連接池,專門負(fù)責(zé)與這個(gè)Tendis節(jié)點(diǎn)進(jìn)行冷熱數(shù)據(jù)恢復(fù)。

1618456780(1).png

用戶訪問一個(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)存。

1.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)存開銷特別大,冷熱混合的收益并不明顯。為了進(jìn)一步釋放內(nèi)存空間,提高緩存的效率,我們放棄了Redis緩存全量Keys的方案,驅(qū)逐的時(shí)候?qū)ey和Value都從緩存層淘汰。

2.Cuckoo Filter解決緩存擊穿和緩存穿透

如果緩存層不存儲(chǔ)全量的Keys,就會(huì)出現(xiàn)緩存擊穿和緩存穿透的問題。為了解決這一問題,緩存層引入Cuckoo Filter表示全量的keys。我們需要一個(gè)支持刪除、可動(dòng)態(tài)伸縮并且空間利用率高的Membership Query結(jié)構(gòu),經(jīng)過我們的調(diào)研和對(duì)比,最終選擇Dynamic Cuckoo Filter。

3.Dynamic Cuckoo Filter實(shí)現(xiàn)

項(xiàng)目初期參考了RedisBloom中Cuckoo Filter的實(shí)現(xiàn),在開發(fā)的過程中也遇到了一些坑,RedisBloom實(shí)現(xiàn)的Cuckoo Filter在刪除的時(shí)候會(huì)出現(xiàn)誤刪,最終給RedisBloom提PR修復(fù)了問題。

4.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)鍵的問題是淘汰和加載策略,這里直接影響緩存的效率,細(xì)分主要有兩點(diǎn):當(dāng)緩存層內(nèi)存滿時(shí),選擇哪些數(shù)據(jù)淘汰?當(dāng)用戶訪問存儲(chǔ)層的數(shù)據(jù)時(shí),是否需要將其放入緩存層?

首先介紹混合存儲(chǔ)的淘汰策略,主要有以下兩個(gè)淘汰策略:

1.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;

2.value-eviction-policy

如果配置value-eviction-policy,后臺(tái)會(huì)定期將用戶N天未訪問的Key/Value被驅(qū)逐出內(nèi)存;

其次講一下緩存加載策略,為了避免緩存污染的問題(比如類似Scan的訪問,遍歷存儲(chǔ)層的數(shù)據(jù),將緩存層真正的熱數(shù)據(jù)淘汰,從而造成了緩存效率低下)。我們實(shí)現(xiàn)緩存加載策略:僅僅將規(guī)定時(shí)間內(nèi)訪問頻率超過某個(gè)閾值的數(shù)據(jù)加載到緩存中,這里的時(shí)間和閾值都是可配置的。

五、基于RDB+AOF擴(kuò)縮容

社區(qū)版Redis的擴(kuò)容流程如下所示:

640.webp (2).jpg

而社區(qū)版Redis擴(kuò)容也存在以下三個(gè)問題:

1.importing和migrating的設(shè)置不是原子的

先設(shè)置目標(biāo)節(jié)點(diǎn)slot為importing狀態(tài),再設(shè)置源節(jié)點(diǎn)的slot為migrating狀態(tài)。如果反過來,由于兩次操作非原子:源節(jié)點(diǎn)設(shè)置為migrating,目標(biāo)節(jié)點(diǎn)還未設(shè)置migrating狀態(tài),請(qǐng)求在這兩個(gè)節(jié)點(diǎn)間反復(fù)Move。

2.搬遷以Key為粒度,效率較低

Migrate命令每次搬遷一個(gè)或者多個(gè)Keys,將整個(gè)Slot搬遷到目標(biāo)節(jié)點(diǎn)需要多次網(wǎng)絡(luò)交互。

3.大Key問題

由于Migrate命令是同步命令,在搬遷過程中是不能處理其他用戶請(qǐng)求的,因此可能會(huì)影響業(yè)務(wù)(延遲時(shí)間波動(dòng)較大)。

由于社區(qū)版Redis存在的上述問題,我們實(shí)現(xiàn)了基于RDB+Aof的擴(kuò)縮容方式,大致流程如下:

1)管控添加新節(jié)點(diǎn),規(guī)劃待搬遷slots;

2)管控端向目標(biāo)節(jié)點(diǎn)下發(fā)slot同步命令:cluster slotsync beginSlot endSlot[[beginSlot endSlot]...]

3)目標(biāo)節(jié)點(diǎn)向源節(jié)點(diǎn)發(fā)送sync[slot...],命令請(qǐng)求同步slot數(shù)據(jù)

4)源節(jié)點(diǎn)生成指定slot數(shù)據(jù)的一致性快照全量數(shù)據(jù)(RDB),并將其發(fā)送給目標(biāo)節(jié)點(diǎn)

5)源節(jié)點(diǎn)開始持續(xù)發(fā)送增量數(shù)據(jù)(Aof)

6)管控端定位獲取源節(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)寫入,然后等待目標(biāo)節(jié)點(diǎn)和源節(jié)點(diǎn)的落后值為0,最后將搬遷的slots歸屬目標(biāo)節(jié)點(diǎn))

1618457044(1).png

同步層Redis-sync

同步層Redis-sync模擬Redis Slave的行為,接收RDB和Aof,然后并行地導(dǎo)入到存儲(chǔ)層Tendis。同步層主要需要解決以下問題:

1)并發(fā)地導(dǎo)入到存儲(chǔ)層Tendis,如何保證時(shí)序正確?

2)特殊命令的處理,比如FLUSHALL/FLUSHDB/SWAPDB/SELECT/MULTI等?

3)作為一個(gè)無狀態(tài)的同步組件,如何保證故障后,數(shù)據(jù)斷點(diǎn)續(xù)傳?

4)緩存層和存儲(chǔ)層分別進(jìn)行擴(kuò)縮容,如何將請(qǐng)求路由到正確的Tendis節(jié)點(diǎn)?

1618457102(1).png

為了解決上述問題,我們實(shí)現(xiàn)了下面的功能:

1.Slot內(nèi)串行,Slot間并行

針對(duì)問題1,Redis-sync中采用與Redis相同的計(jì)算Slot的算法,解析到具體的命令后,根據(jù)Key所屬的slot,將其放到對(duì)應(yīng)的隊(duì)列中(slot%QueueSize)。因此同一個(gè)Slot的數(shù)據(jù)是串行寫入,不同slot的數(shù)據(jù)可以并行寫入,不會(huì)出現(xiàn)時(shí)序錯(cuò)亂的行為。

2.串并轉(zhuǎn)換

針對(duì)問題2,Redis-sync會(huì)在并行和串行模式之間進(jìn)行轉(zhuǎn)換。比如收到FLUSHDB命令,這是需要將FLUSHDB命令前的命令都執(zhí)行完,再執(zhí)行FLUSHDB命令。

3.定期上報(bào)

針對(duì)問題3,Redis-sync會(huì)定期將已發(fā)送給存儲(chǔ)層的aof的Version持久化到存儲(chǔ)層。如何Redis-sync故障,首先從存儲(chǔ)層獲取上次已發(fā)送的位置,然后向?qū)?yīng)的Redis節(jié)點(diǎn)發(fā)送psync,請(qǐng)求同步。

4.數(shù)據(jù)自動(dòng)路由

針對(duì)問題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ù)庫,主要具有以下特性:

1.兼容Redis協(xié)議

完全兼容redis協(xié)議,支持redis主要數(shù)據(jù)結(jié)構(gòu)和接口,兼容大部分原生Redis命令。

2.持久化存儲(chǔ)

使用rocksdb作為存儲(chǔ)引擎,所有數(shù)據(jù)以特定格式存儲(chǔ)在rocksdb中,最大支持PB級(jí)存儲(chǔ)。

3.去中心化架構(gòu)

類似于redis cluster的分布式實(shí)現(xiàn),所有節(jié)點(diǎn)通過gossip協(xié)議通訊,可指定hashtag來控制數(shù)據(jù)分布和訪問,使用和運(yùn)維成本極低。

4.水平擴(kuò)展

集群支持增刪節(jié)點(diǎn),并且數(shù)據(jù)可以按照slot在任意兩節(jié)點(diǎn)之間遷移,擴(kuò)容和縮容過程中對(duì)應(yīng)用運(yùn)維人員透明,支持?jǐn)U展至1000個(gè)節(jié)點(diǎn)。

5.故障自動(dòng)切換

自動(dòng)檢測(cè)故障節(jié)點(diǎn),當(dāng)故障發(fā)生后,slave會(huì)自動(dòng)提升為master繼續(xù)對(duì)外提供服務(wù)。

640.webp (5).jpg

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于騰訊云數(shù)據(jù)庫,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
相關(guān)文章
騰訊云數(shù)據(jù)庫PostgreSQL全面支持PG 17
騰訊云數(shù)據(jù)庫PostgreSQL全面支持PG 17
即日起,騰訊云PostgreSQL全面支持PostgreSQL 17.0。所有用戶可使用大版本升級(jí)能力升級(jí)至最新的PostgreSQL 17.0進(jìn)行體驗(yàn),也可以在產(chǎn)品購(gòu)買頁直接購(gòu)買。
騰訊云
云服務(wù)
2024-12-152024-12-15
高可用這個(gè)問題,加機(jī)器就能解決?
高可用這個(gè)問題,加機(jī)器就能解決?
互聯(lián)網(wǎng)服務(wù)的可用性問題是困擾企業(yè)IT人員的達(dá)摩克利斯之劍:防于未然,體現(xiàn)不出價(jià)值。已然發(fā)生,又面臨P0危機(jī)。就更別提穩(wěn)定性建設(shè)背后顯性的IT預(yù)算問題與隱性的人員成本問題。
騰訊云
云服務(wù)
2024-11-252024-11-25
TDSQL TDStore引擎版替換HBase:在歷史庫場(chǎng)景中的成本與性能優(yōu)勢(shì)
TDSQL TDStore引擎版替換HBase:在歷史庫場(chǎng)景中的成本與性能優(yōu)勢(shì)
HBase憑借其高可用性、高擴(kuò)展性和強(qiáng)一致性,以及在廉價(jià)PC服務(wù)器上的低部署成本,廣泛應(yīng)用于大規(guī)模數(shù)據(jù)分析。
騰訊云
云服務(wù)
2024-11-042024-11-04
復(fù)雜查詢性能弱,只讀分析引擎來幫忙
復(fù)雜查詢性能弱,只讀分析引擎來幫忙
隨著當(dāng)今業(yè)務(wù)的高速發(fā)展,復(fù)雜多表關(guān)聯(lián)的場(chǎng)景越來越普遍。但基于行式存儲(chǔ)的數(shù)據(jù)庫在進(jìn)行復(fù)雜查詢時(shí)性能相對(duì)較弱。
騰訊云
云服務(wù)
2024-11-022024-11-02
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號(hào)后即可登錄/注冊(cè)
加載中
二維碼已失效 請(qǐng)重試
刷新
賬號(hào)登錄/注冊(cè)
個(gè)人VIP
小程序
快出海小程序
公眾號(hào)
快出海公眾號(hào)
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家