RedKV是紅書自研的一款基于NVMeSSD的分布式noSQL KV存儲(chǔ)系統(tǒng),支持無(wú)中心和有中心的兩種管控架構(gòu),旨在解決公司內(nèi)實(shí)時(shí)落盤的KV存儲(chǔ)需求。RedKV1.0基于Gossip協(xié)議做節(jié)點(diǎn)管理,在全公司已經(jīng)大規(guī)模使用,實(shí)時(shí)QPS接近1億/秒,存儲(chǔ)量在數(shù)PB級(jí)別。RedKV2.0采用中心Shard管理架構(gòu),支持全球多云多副本在線彈性伸縮,異地容災(zāi)和服務(wù)秒級(jí)切換。

通過(guò)分層優(yōu)化,RedKV對(duì)比開源同類產(chǎn)品,聚合寫吞吐能力平均提升3倍,讀1.5倍;對(duì)標(biāo)HBase,成本優(yōu)化近40%。RedKV部分兼容Redis協(xié)議,string/hash/zset等主要數(shù)據(jù)類型很好的的支持了公司的絕大部分在線存儲(chǔ)業(yè)務(wù),優(yōu)化了早期Redis集群部署產(chǎn)生的成本問(wèn)題以及HBase帶來(lái)的性能及穩(wěn)定性問(wèn)題。RedKV和hive數(shù)倉(cāng)的數(shù)據(jù)互通能力為離線數(shù)據(jù)業(yè)務(wù)提供了一種解決方案。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

小紅書是年輕人的生活記錄、分享平臺(tái),用戶可以通過(guò)短視頻、圖文等形式記錄生活點(diǎn)滴,分享生活方式。在當(dāng)前的業(yè)務(wù)模型下,用戶的畫像數(shù)據(jù)和筆記數(shù)據(jù)用來(lái)做風(fēng)險(xiǎn)控制和內(nèi)容推薦。存儲(chǔ)數(shù)據(jù)具有對(duì)象-屬性的特征、維度多,畫像數(shù)據(jù)量已經(jīng)達(dá)到數(shù)十TB, 在線業(yè)務(wù)對(duì)畫像和筆記數(shù)據(jù)的訪問(wèn)P99 時(shí)延要求非常高。

2020年之前公司選擇的NoSQL存儲(chǔ)產(chǎn)品主要有:Redis、HBase,隨著公司DAU的高速增長(zhǎng),早期的存儲(chǔ)方案遇到如下挑戰(zhàn):

  • Redis集群主要適用于緩存場(chǎng)景,開啟AOF數(shù)據(jù)實(shí)時(shí)落盤對(duì)性能有比較大的影響,同時(shí)每個(gè)節(jié)點(diǎn)需要額外掛載云盤用于存儲(chǔ)AOF。在集群節(jié)點(diǎn)和存儲(chǔ)容量受限的情況下,單節(jié)點(diǎn)的數(shù)據(jù)量設(shè)置過(guò)大會(huì)導(dǎo)致故障后節(jié)點(diǎn)數(shù)據(jù)的failover時(shí)間太長(zhǎng),單節(jié)點(diǎn)數(shù)據(jù)量設(shè)置小會(huì)導(dǎo)致gossip協(xié)議在穩(wěn)定性高要求下節(jié)點(diǎn)個(gè)數(shù)受限,同時(shí)考慮突發(fā)流量的壓力,Redis集群在部署上需要做一些空間預(yù)留,帶來(lái)成本高的問(wèn)題。
  • HBase作為一款生態(tài)完善的NoSQL存儲(chǔ)系統(tǒng),在高QPS下也產(chǎn)生了諸多的性能和穩(wěn)定性問(wèn)題,如:Zookeeper壓力大時(shí)穩(wěn)定性難以保障(節(jié)點(diǎn)探活,服務(wù)注冊(cè)等都依賴 Zookeeper);HBase的數(shù)據(jù)文件和WAL日志文件直接寫HDFS,節(jié)點(diǎn)故障后,重放HDFS上的WAL速度慢;Java GC會(huì)導(dǎo)致Zookeeper誤殺RegionServer,同時(shí)產(chǎn)生毛刺;Major Compaction 會(huì)導(dǎo)致I/O飆升,產(chǎn)生長(zhǎng)尾效應(yīng);受限HDFS的復(fù)雜性,黑盒運(yùn)維對(duì)工程師來(lái)說(shuō)比較困難;在小紅書的業(yè)務(wù)實(shí)戰(zhàn)中,百萬(wàn)QPS下HBase延時(shí)不太理想,核心數(shù)據(jù)用大內(nèi)存機(jī)型兜住,也引發(fā)成本高的問(wèn)題。

隨著業(yè)務(wù)的持續(xù)增長(zhǎng),開源存儲(chǔ)產(chǎn)品已經(jīng)不能很好的滿足公司的業(yè)務(wù)發(fā)展需求, 公司需要一款穩(wěn)定的高性能KV系統(tǒng)支撐內(nèi)部業(yè)務(wù),一方面要滿足業(yè)務(wù)對(duì)功能和性能的需求,另一方面要優(yōu)化成本。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

2.1. 高QPS和低延時(shí)讀取特性

特征數(shù)據(jù)存儲(chǔ)場(chǎng)景:

  • 寫入帶寬達(dá)到數(shù)十GB/s,要求實(shí)時(shí)寫入性能和讀取性能都很高。

圖片緩存的場(chǎng)景:

  • 數(shù)據(jù)量很大,要求讀取時(shí)延低??梢越邮芄收蠄?chǎng)景下少量數(shù)據(jù)丟失。

高性能(P99 < 10ms):

  • 模型數(shù)據(jù)存儲(chǔ)服務(wù)。記錄過(guò)去一段時(shí)間用戶訓(xùn)練模型數(shù)據(jù),對(duì)P99時(shí)延要求非常高,數(shù)據(jù)量在幾十TB。
  • 去重存儲(chǔ)服務(wù)。數(shù)據(jù)量在幾十TB,P99<10ms, P999<20ms。
  • 風(fēng)控?cái)?shù)據(jù)存儲(chǔ)服務(wù)。QPS目前達(dá)到千萬(wàn)級(jí)別,P999 < 30ms。

2.2. 低成本的緩存特性

對(duì)標(biāo)Redis:

  • 兼容Redis協(xié)議,性能比Redis慢一些,但資源成本降低50%+。

典型場(chǎng)景:

  • 廣告的關(guān)鍵詞存儲(chǔ)和反作弊業(yè)務(wù),解決大數(shù)據(jù)量、低QPS的存儲(chǔ)模型。

2.3. NoSQL存儲(chǔ)特性

對(duì)標(biāo)HBase:

  • 支持?jǐn)?shù)據(jù)多版本,列存行取等特性,比HBase成本減少30%+,P99時(shí)延提升6倍。
  • 支持KKV級(jí)別的TTL。
  • 強(qiáng)一致:目前RedKV1.0采用的主從雙副本,數(shù)據(jù)寫入成功,可以通過(guò)配置同步模式來(lái)保障2副本寫成功,讀主寫主保障強(qiáng)一致。對(duì)于寫性能要求高的場(chǎng)景,可以打開異步寫,寫主成功則返回,依賴增量同步從節(jié)點(diǎn)數(shù)據(jù)。

典型場(chǎng)景:

  • 風(fēng)控服務(wù)。實(shí)時(shí)查詢對(duì)P999要求極高,千萬(wàn)QPS下HBase已經(jīng)不能滿足性能需求,時(shí)延抖動(dòng)比較大。
  • 畫像存儲(chǔ)服務(wù)。數(shù)據(jù)的維度多,字段讀取的業(yè)務(wù)方多,對(duì)時(shí)延要求敏感。
小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

RedKV整體架構(gòu)分3層,接入層兼容Redis協(xié)議,支持各種語(yǔ)言的社區(qū)版SDK和公司定制的中間件版;接入代理層支持千萬(wàn)QPS的讀寫能力,無(wú)狀態(tài)擴(kuò)展;存儲(chǔ)層提供高可靠讀寫服務(wù)。RedKV1.0架構(gòu)如下圖1,下面我們?cè)敿?xì)的展開3層組件的介紹。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖1. RedKV1.0整體架構(gòu)

3.1. Client接入層

RedKV集群部署完成后,通過(guò)公司內(nèi)部提供的Service Mesh組件做服務(wù)發(fā)現(xiàn),對(duì)Client提供服務(wù)。

3.2. Proxy

Proxy層由一個(gè)無(wú)狀態(tài)CorvusPlus進(jìn)程組成。它兼容老的Redis Client,擴(kuò)縮容、升級(jí)對(duì)無(wú)Client和后端集群無(wú)感,支持多線程、IO多路復(fù)用和端口復(fù)用特性。對(duì)比開源版本,CorvusPlus增強(qiáng)了自我防護(hù)和可觀測(cè)特性,實(shí)現(xiàn)了可在線配置的功能特性:

  • Proxy限流
  • 數(shù)據(jù)在線壓縮
  • 線程模型優(yōu)化
  • backup-read優(yōu)化長(zhǎng)尾
  • 大key檢測(cè)

3.2.1. Proxy限流

小紅書當(dāng)前的業(yè)務(wù)模型比較多,客戶端行為無(wú)法預(yù)期,可能出現(xiàn)的發(fā)版錯(cuò)誤、系統(tǒng)問(wèn)題及網(wǎng)絡(luò)抖動(dòng)引發(fā)客戶端重試,突發(fā)的qps會(huì)影響服務(wù)穩(wěn)定性。在高QPS壓力下,Proxy處理客戶端讀寫超時(shí),大量重試會(huì)導(dǎo)致雪崩,業(yè)務(wù)高峰期單個(gè) Proxy 帶寬可能超過(guò)機(jī)器的出入帶寬限制,而存儲(chǔ)集群只能保證在有限的資源內(nèi)提供穩(wěn)定可靠的服務(wù)。針對(duì)這類場(chǎng)景,我們需要保證流量過(guò)載時(shí),Proxy和RedKV服務(wù)不被打崩,能保障高可用。

基于以上問(wèn)題和目標(biāo),對(duì)比原生的Redis Cluster模式,RedKV基于令牌桶的流控算法支持了對(duì)連接數(shù)、帶寬和QPS多維度限流。在高QPS下,我們的Proxy限流防止了雪崩,如圖2;在大帶寬場(chǎng)景下,我們優(yōu)化了時(shí)延,如圖3。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖2. 雪崩場(chǎng)景下的限流

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖3. 大帶寬場(chǎng)景下的限流

3.2.2. 數(shù)據(jù)在線壓縮

Proxy層本身只做路由轉(zhuǎn)發(fā),對(duì)CPU的消耗非常低。在大帶寬的場(chǎng)景下,我們可以充分利用Proxy的CPU資源優(yōu)化帶寬和毛刺。在解析Redis協(xié)議時(shí),使用LZ4算法對(duì)寫入數(shù)據(jù)進(jìn)行在線壓縮,讀取時(shí)在線解壓。在推薦緩存的使用場(chǎng)景中網(wǎng)絡(luò)帶寬和存儲(chǔ)空間壓縮40%以上(如圖4),總體時(shí)延并沒(méi)有明顯的下降。因?yàn)榫W(wǎng)絡(luò)帶寬和寫入讀取數(shù)據(jù)的減少,時(shí)延毛刺也變小了。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖4. Proxy開壓縮后的帶寬優(yōu)化

3.2.3. 線程模型的優(yōu)化

Proxy采用IO多路復(fù)用技術(shù),每個(gè)連接維護(hù)一個(gè)請(qǐng)求處理隊(duì)列和響應(yīng)隊(duì)列,保序的返回給客戶端。Proxy在收到RedKV Server的回應(yīng)之后,如果沒(méi)有收到所有發(fā)送的cmd的返回,則會(huì)一直等待所有cmd的返回后再發(fā)送給client,對(duì)于讀的場(chǎng)景這種模式非常不友好。經(jīng)過(guò)改造,如果某個(gè)cmd之前的cmd都已經(jīng)正常響應(yīng),則可以馬上響應(yīng)給client,不需要再等后面的所有cmd請(qǐng)求完成。

3.2.4. backup-read優(yōu)化長(zhǎng)尾

公網(wǎng)環(huán)境下,一個(gè)CVM虛擬機(jī)和其他多個(gè)虛擬機(jī)共享一臺(tái)物理機(jī)。當(dāng)某個(gè)客戶的CVM占用大量資源時(shí),很容易影響到其他CVM的P99時(shí)延(由于QOS和隔離性做的不夠好,SMI中斷和內(nèi)存CE)。在網(wǎng)絡(luò)吞吐較大的情況下,某云的DPDK容易被打爆,出現(xiàn)母機(jī)OOB。而在RedKV的內(nèi)部實(shí)現(xiàn)中,如果Server請(qǐng)求比較大,某些key的查詢時(shí)延比較高的時(shí)候,容易產(chǎn)生排隊(duì)堆積,或者compaction之后的block cache失效,很容易造成IO長(zhǎng)尾。因此,RedKV的P99讀時(shí)延的毛刺很難避免,但毛刺是偶爾發(fā)生的,當(dāng)前我們的主從節(jié)點(diǎn)一定是離散部署在不同的母機(jī)上,同時(shí)出現(xiàn)P99毛刺的可能很小?;谶@點(diǎn),我們?cè)赑roxy層做了backup read功能,優(yōu)化了RedKV的p99時(shí)延問(wèn)題。

針對(duì)以上模型,我們的優(yōu)化思路:

  • 檢查節(jié)點(diǎn)的狀態(tài)和過(guò)去的延時(shí)
  • 選擇2個(gè)節(jié)點(diǎn)中狀態(tài)好的那個(gè)節(jié)點(diǎn)發(fā)送請(qǐng)求
  • 計(jì)算P99時(shí)延,超過(guò)P95時(shí)延則向另外一個(gè)節(jié)點(diǎn)發(fā)送一定數(shù)目的backup read請(qǐng)求數(shù)
  • 兩個(gè)請(qǐng)求中任意一個(gè)請(qǐng)求返回成功則成功,如果超時(shí)則繼續(xù)重試

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖5. Backup-read 消峰

因?yàn)閎ackup read轉(zhuǎn)發(fā)不需要復(fù)制內(nèi)存,通過(guò)索引來(lái)保證生命周期,而且只有超過(guò)P95時(shí)延的報(bào)文會(huì)被檢查是否能發(fā)送backup read,因此,只要5%的報(bào)文會(huì)發(fā)送兩次,對(duì)集群基本不會(huì)增加壓力。圖6為一個(gè)集群中 P999從35ms降低到4ms左右,效果非常明顯。對(duì)比HBase同樣的業(yè)務(wù)場(chǎng)景,客戶端在同樣的timeout的配置下,我們的方案提高了客戶端的成功率。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖6. Backup-read P999優(yōu)化對(duì)比

3.2.5. 大Key檢測(cè)

我們線上很多集群在業(yè)務(wù)使用過(guò)程中會(huì)偶發(fā)的產(chǎn)生一些毛刺,通過(guò)抓包發(fā)現(xiàn),這里毛刺有很大一部分原因是因?yàn)榇驥ey造成的。為了甄別這類問(wèn)題,我們?cè)赑roxy層支持的大Key的可觀測(cè)指標(biāo)。Proxy在解析Redis的cmd可以附帶統(tǒng)計(jì)KV的大小。對(duì)于string讀類型的command,讀到的val值大于 big-string-size 判定為大key;對(duì)于寫類型的command, 請(qǐng)求值大于 big-string-size 判定為大key;對(duì)于hash/zset則為一次讀取的kv總數(shù)大小。通過(guò)增加read_size(所有讀請(qǐng)求總共讀到的字節(jié)數(shù)) 和 write_size (所有寫請(qǐng)求總共寫入的字節(jié)數(shù))監(jiān)控,rate(read_size) / rate(total_req_amount) 可以計(jì)算出平均請(qǐng)求值大小。大Key和熱Key是KV系統(tǒng)不可避免的2個(gè)場(chǎng)景,針對(duì)大Key,我們提供了Proxy層的數(shù)據(jù)壓縮能力;對(duì)于熱Key, 我們?cè)赟erver層基于HeavyKeeper[3]算法做了topK統(tǒng)計(jì)和處理。

3.3. RedKV Cluster

公司的存儲(chǔ)需求場(chǎng)景比較多,如廣告業(yè)務(wù)存儲(chǔ)的標(biāo)簽和數(shù)據(jù)模型很多,同時(shí)是非常核心的業(yè)務(wù),業(yè)務(wù)需要做資源隔離。為了減少節(jié)點(diǎn)故障縮小數(shù)據(jù)的爆炸半徑 ,這里業(yè)務(wù)我們采用無(wú)中心管控的架構(gòu),即RedKV1.0架構(gòu),它能在部署和運(yùn)維上能大大簡(jiǎn)化。無(wú)中心的集群架構(gòu)采用的是Gossip協(xié)議,存儲(chǔ)節(jié)點(diǎn)采用多進(jìn)程多實(shí)例部署,如圖7。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖7. Gossip管控的KV Cluster

推薦模型訓(xùn)練的數(shù)據(jù)量非常大,上下游業(yè)務(wù)很多,承載的QPS高,對(duì)應(yīng)集群的節(jié)點(diǎn)也比較多,在故障處理和擴(kuò)縮容方面會(huì)觸發(fā)gossip抖動(dòng)。針對(duì)大集群的節(jié)點(diǎn)管理,我們采用有中心管控的架構(gòu),即RedKV2.0架構(gòu)?;赟hard管理的中心架構(gòu)能更好的支持數(shù)據(jù)遷移和集群擴(kuò)縮容,存儲(chǔ)節(jié)點(diǎn)采用單進(jìn)程多實(shí)例部署,在多活場(chǎng)景中可以支持副本數(shù)彈性擴(kuò)展,如圖8。RedKV2.0的相關(guān)組件會(huì)在后續(xù)的技術(shù)文章中詳細(xì)介紹。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖8. 基于中心管控的KV Cluster

3.3.1. Gossip優(yōu)化

RedKV1.0采用Gossip協(xié)議通信,節(jié)點(diǎn)故障時(shí)主從節(jié)點(diǎn)的切換,最長(zhǎng)影響時(shí)間為30s。一個(gè)節(jié)點(diǎn)出現(xiàn)故障時(shí),集群中正常節(jié)點(diǎn)將故障節(jié)點(diǎn)標(biāo)記為 fail 狀態(tài)需要經(jīng)過(guò)一段收斂時(shí)間。在這段時(shí)間內(nèi),Proxy層有可能將用戶請(qǐng)求轉(zhuǎn)發(fā)給已經(jīng) fail 的節(jié)點(diǎn),導(dǎo)致請(qǐng)求失敗。減小集群收斂時(shí)間能有效減少Proxy層錯(cuò)誤請(qǐng)求數(shù)量,提高集群的穩(wěn)定性和可用性。

RedKV1.0通過(guò)如下三個(gè)步驟加快視圖收斂:

  • 探測(cè)時(shí)間優(yōu)化:Redis Gossip協(xié)議正常情況下會(huì)每隔100ms隨機(jī)選取一個(gè)節(jié)點(diǎn)發(fā)送ping包,并更新節(jié)點(diǎn)的ping_sent值為發(fā)送ping包時(shí)間。如果集群很大,節(jié)點(diǎn)數(shù)很多,那么故障節(jié)點(diǎn)被ping到的概率就會(huì)變小,最多超過(guò)node_timeout/2時(shí)間給故障節(jié)點(diǎn)發(fā)送ping包。這樣就會(huì)導(dǎo)致節(jié)點(diǎn)發(fā)生故障時(shí),集群中正常節(jié)點(diǎn)不能第一時(shí)間ping到故障節(jié)點(diǎn),從而無(wú)法立刻感知到故障節(jié)點(diǎn)發(fā)生了故障。為了減少這部分時(shí)間,當(dāng)集群中有節(jié)點(diǎn)超過(guò)2s沒(méi)有收到故障節(jié)點(diǎn)發(fā)送的pong報(bào)文時(shí),就立馬通知其他節(jié)點(diǎn)去ping故障節(jié)點(diǎn)。這樣可以把節(jié)點(diǎn)故障到正常節(jié)點(diǎn)給故障節(jié)點(diǎn)發(fā)送ping的時(shí)間控制在2s左右。
  • 判定PFAIL時(shí)間優(yōu)化:Gossip 協(xié)議現(xiàn)有實(shí)現(xiàn)方式是超過(guò)node_timeout(通常為15s)時(shí)間沒(méi)有收到pong報(bào)文,就將節(jié)點(diǎn)狀態(tài)置為pfail。本次優(yōu)化將這個(gè)時(shí)間設(shè)置為3s(可配置),如果24小時(shí)內(nèi)(可配置)首次超過(guò)3s沒(méi)有收到pong報(bào)文,就將節(jié)點(diǎn)置為pfail狀態(tài)。如果24小時(shí)內(nèi)頻繁出現(xiàn),那可能是網(wǎng)絡(luò)抖動(dòng)造成,還走原來(lái)的路徑等待node_timeout。
  • 減少PFAIL到FAIL的判定時(shí)間:只有一個(gè)節(jié)點(diǎn)收到集群1/2的節(jié)點(diǎn)的PFAIL信息的時(shí)候,才會(huì)將故障節(jié)點(diǎn)判定為FAIL狀態(tài)。而PFAIL這個(gè)信息是通過(guò)Gossip協(xié)議交互的,最久需要1/2 node_timeout才會(huì)通知到其他節(jié)點(diǎn)。因此為了加速PFAIL到FAIL的狀態(tài),所有的節(jié)點(diǎn)按照統(tǒng)一的規(guī)則選出一個(gè)種子節(jié)點(diǎn),PFAIL信息除了隨機(jī)發(fā)送一個(gè)節(jié)點(diǎn)意外,還會(huì)通知這個(gè)種子節(jié)點(diǎn)。這樣種子節(jié)點(diǎn)能在最快的時(shí)間學(xué)習(xí)到集群所有節(jié)點(diǎn)的PFAIL信息,從而將故障節(jié)點(diǎn)標(biāo)記為FAIL狀態(tài)廣播到集群。

3.3.2. RedKV Server

RedKV Server配置多個(gè)IO線程同時(shí)監(jiān)聽一個(gè)端口來(lái)接受連接請(qǐng)求,每個(gè)線程上的連接數(shù)目會(huì)隨機(jī)均衡。每個(gè)線程只解析自己連接上的請(qǐng)求,并將解析出的報(bào)文通過(guò)key掛到對(duì)應(yīng)的請(qǐng)求隊(duì)列上,每個(gè)隊(duì)列由一個(gè)Worker線程處理。這樣同一個(gè)key/同一個(gè)slot上的請(qǐng)求都會(huì)落到同一根Worker線程上處理,避免了對(duì)key進(jìn)行加鎖,減少鎖沖突和線程切換。Worker線程中會(huì)對(duì)數(shù)據(jù)進(jìn)行重編碼,存儲(chǔ)到Rocksdb本地存儲(chǔ)引擎。

RedKV內(nèi)部的線程模型如下圖9:

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖9. RedKV Server無(wú)鎖線程模型

3.3.3. 數(shù)據(jù)存儲(chǔ)

RedKV當(dāng)前支持的數(shù)據(jù)類型有string、hash和zset,數(shù)據(jù)節(jié)點(diǎn)選擇RocksDB[2]作為本地存儲(chǔ)引擎,集群創(chuàng)建時(shí)支持配置多副本,主從節(jié)點(diǎn)離散部署。采用hash打散的方式存儲(chǔ)連續(xù)slot分片的數(shù)據(jù),能比較好的避免熱點(diǎn)key問(wèn)題。不同的數(shù)據(jù)類型包含(MetaKey,MetaValue) 和(DataKey, DataValue),設(shè)計(jì)格式如下:

MetaKey:

MetaValue:

DataKey:

DataValue:

在如上的編碼方式下,key的設(shè)計(jì)中保留的slot信息,可以在擴(kuò)縮容的場(chǎng)景中通過(guò)slot靈活的做數(shù)據(jù)遷移。

4.1. 數(shù)據(jù)復(fù)制

與傳統(tǒng)解決方案引入同步組件的方式不同,我們快速實(shí)現(xiàn)了單向數(shù)據(jù)同步以及集群擴(kuò)容需求,整體架構(gòu)去除了對(duì)第三方組件的依賴,通過(guò)擴(kuò)展Redis復(fù)制協(xié)議實(shí)現(xiàn)了RedKV數(shù)據(jù)節(jié)點(diǎn)的直接復(fù)制,如圖10。單向復(fù)制的限制是擴(kuò)容需要基于2n做節(jié)點(diǎn)同步,擴(kuò)容完成后后臺(tái)任務(wù)根據(jù)3.3.3中定義的key的分片刪除不是本節(jié)點(diǎn)的數(shù)據(jù)。

在多活的部署形態(tài)下,多云集群的一對(duì)多的數(shù)據(jù)復(fù)制采用單向復(fù)制對(duì)主集群性能侵入較大,因此我們實(shí)現(xiàn)了基于中心管控的數(shù)據(jù)復(fù)制策略。該策略支持多個(gè)集群的分片異構(gòu)部署,通過(guò)Checkpoint方式定向同步數(shù)據(jù),不再需要額外的后臺(tái)任務(wù)去做數(shù)據(jù)淘汰,能很好的支持多對(duì)多的多云集群數(shù)據(jù)復(fù)制、數(shù)據(jù)破環(huán)和擴(kuò)縮容。

圖10. RedKV的數(shù)據(jù)復(fù)制

4.2. 數(shù)據(jù)批量導(dǎo)入

小紅書大量的離線業(yè)務(wù)數(shù)據(jù)存儲(chǔ)在S3 Hive中,每天會(huì)有部分?jǐn)?shù)據(jù)需要增量更新,其他的數(shù)據(jù)會(huì)被淘汰。這類場(chǎng)景有幾個(gè)挑戰(zhàn):

  • 批量導(dǎo)入:如小紅書的筆記數(shù)據(jù),一般需要小時(shí)級(jí)別甚至天級(jí)別的更新,所以業(yè)務(wù)需要有快捷的批量導(dǎo)入功能。
  • 快速更新:特征數(shù)據(jù)的特點(diǎn)就是數(shù)據(jù)量特別大,以筆記為例,全量筆記在TB 級(jí)別數(shù)據(jù)量。如果通過(guò) Jedis SDK 寫入,那么存儲(chǔ)集群需要支持百萬(wàn)QPS的機(jī)器資源。當(dāng)下小紅書數(shù)據(jù)平臺(tái)支持業(yè)務(wù)把數(shù)據(jù)從hive通過(guò)工作流直接導(dǎo)入RedKV,一般是每天凌晨開始寫數(shù)據(jù),等到晚高峰時(shí)大量讀取。這種方法實(shí)踐下來(lái),經(jīng)常導(dǎo)致 RedKV集群的集群內(nèi)存OOM,影響穩(wěn)定性。
  • 性能及穩(wěn)定:數(shù)據(jù)在導(dǎo)入的過(guò)程中不能影響讀的性能

實(shí)現(xiàn)方案如圖11:

  • 自定義獲取集群視圖和數(shù)據(jù)編碼的UDTF,支持RedKV1.0的數(shù)據(jù)格式
  • 將原先的抽數(shù)據(jù),編碼,分片和排序整合成一個(gè)HiveOperator,執(zhí)行完成后按指定的OutputFormat輸出SST文件到一個(gè)指定S3目錄
  • 通過(guò)Hadoop distcp工具做數(shù)據(jù)的跨云傳輸,走離線帶寬不影響線上的讀寫業(yè)務(wù)
  • RedKV集群的節(jié)點(diǎn)SiderCar作為對(duì)象存儲(chǔ)的一個(gè)Client,RedKV節(jié)點(diǎn)加載本節(jié)點(diǎn)的SST并ingest

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖11. 離線數(shù)據(jù)BulkLoad

4.3. 數(shù)據(jù)批量導(dǎo)出

小紅書的業(yè)務(wù)模型訓(xùn)練數(shù)據(jù)通過(guò)Hash存儲(chǔ)在RedKV集群中,業(yè)務(wù)下游需要對(duì)訓(xùn)練結(jié)果進(jìn)行離線分析,希望RedKV具有和Hive數(shù)據(jù)流通的能力。RedKV本身是不支持Schema的,如果要將KV數(shù)據(jù)導(dǎo)入Hive表,則需要將Hash的KKV數(shù)據(jù)轉(zhuǎn)化為一個(gè)Table。

RedKV的內(nèi)部數(shù)據(jù)按hash打散,導(dǎo)入Hive表則需要提供table關(guān)鍵字,先按前綴掃描的方式掃描存儲(chǔ)節(jié)點(diǎn),再生成Hive識(shí)別的文件,最后通過(guò)Hive Load進(jìn)行加載。為了更好的兼容其他spark任務(wù),我們選擇Hive支持的標(biāo)準(zhǔn)parquet列式存儲(chǔ)文件,整個(gè)I/O鏈路如下圖12:

圖12. RedKV2Hive I/O

示例:RedKV里面的Key 寫入規(guī)定以 {tablename}_ 開始,比如一個(gè)artical表

RedKV中的數(shù)據(jù)采用hmset寫入:

hmset {person}_1 name John quantity 20 price 200.23
hmset {person}_2 name Henry quantity 30 price 3000.45

通過(guò)以上的寫入方式,可以通過(guò)配置RedKV2Hive 將KV里面的數(shù)據(jù)導(dǎo)入到Hive里面的Person表 如果單表的數(shù)據(jù)量很大,可以采用分表寫入,比如把person表分成16份

hmset {person:1}_1 name John quantity 20 price 200.23
hmset {person:1}_2 name Henry quantity 30 price 3000.45
...
hmset {person:16}_100000 name Tom quantity 43 price 234.56

4.4. 數(shù)據(jù)的備份和恢復(fù)

小紅書的廣告數(shù)據(jù)存儲(chǔ)在自研的分布式KV系統(tǒng)中,數(shù)據(jù)安全主要面臨如下挑戰(zhàn):

  • 基于LSM結(jié)構(gòu)的KV系統(tǒng),數(shù)據(jù)compaction導(dǎo)致的空間放大會(huì)翻倍,數(shù)據(jù)量大后,數(shù)據(jù)備份需要大容量的磁盤
  • 單集群故障后,集群恢復(fù)的時(shí)間不可控
  • 備份數(shù)據(jù)依賴第三方系統(tǒng)
  • 廣告系統(tǒng)對(duì)數(shù)據(jù)的及時(shí)恢復(fù)能力有比較高的要求,通常要求在分鐘級(jí)。為了解決上述幾個(gè)問(wèn)題,我們提出了一種中心管控的主備集群容災(zāi)策略,通過(guò)Proxy接入層的秒級(jí)切換能快速切流到一個(gè)特定的版本

實(shí)現(xiàn)方案如圖13:

  • 先部署一個(gè)容災(zāi)集群,主集群對(duì)外提供讀寫服務(wù),災(zāi)備集群保存特定數(shù)量的快照數(shù)據(jù)
  • 低峰期,中心管控根據(jù)配置的版本數(shù)和任務(wù)時(shí)間會(huì)定時(shí)的向主集群發(fā)送打快照的服務(wù)
  • 快照完成后通過(guò)發(fā)生遠(yuǎn)程rsync命令將快照目錄傳送到容災(zāi)集群,主集群低峰期數(shù)據(jù)壓縮后數(shù)據(jù)量可控,這樣災(zāi)備集群可以備份指定數(shù)量的版本信息
  • 故障發(fā)生后,中心管控可以在災(zāi)備集群通過(guò)RPC指令指定恢復(fù)到一個(gè)特定的版本
  • Proxy接入層通過(guò)服務(wù)注冊(cè)與發(fā)現(xiàn)主鍵配置2組服務(wù),通過(guò)動(dòng)態(tài)的秒級(jí)切換可以將流量打向特定版本的集群,完成服務(wù)訪問(wèn)的秒級(jí)切換

圖13. 集群備份

4.5. 跨云多活

為了應(yīng)對(duì)高速增長(zhǎng)的業(yè)務(wù)需求,公司對(duì)云廠商的服務(wù)穩(wěn)定性要求越來(lái)越高,單機(jī)房云服務(wù)難以滿足公司穩(wěn)定性的需求,跨云多活可以提高服務(wù)的穩(wěn)定性,雙寫雙讀可以實(shí)現(xiàn)主備數(shù)據(jù)中心均對(duì)外提供讀寫服務(wù), 這樣既不會(huì)造成數(shù)據(jù)中心的資源浪費(fèi)又可以實(shí)現(xiàn)跨地域容災(zāi)。我們對(duì)業(yè)界常用的方案做了一些對(duì)比分析:

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

我們綜合調(diào)研其他廠商的架構(gòu)經(jīng)驗(yàn),提出了RedKV雙活設(shè)計(jì)( Replicator as Sidecar Service同機(jī)部署) 方案,如圖14。

  • 同機(jī)部署,網(wǎng)絡(luò)開銷?。?/span>
  • Sidecar Service 對(duì)主服務(wù)侵入性??;
  • 單獨(dú)部署,易于升級(jí)

架構(gòu)靈活,適合日志類存儲(chǔ)系統(tǒng)雙活架構(gòu)。Redis 以及圖數(shù)據(jù)庫(kù)的多云方案都可以改造適用,具體的功能組件和實(shí)戰(zhàn)場(chǎng)景會(huì)在后續(xù)技術(shù)文章詳細(xì)介紹。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖14. 跨云多活架構(gòu)

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

正如第2節(jié)描述的小紅書業(yè)務(wù)需求場(chǎng)景,本節(jié)通過(guò)一個(gè)典型的業(yè)務(wù)場(chǎng)景來(lái)展示RedKV在noSQL存儲(chǔ)下的收益。

早期在沒(méi)有zprofile中臺(tái)的場(chǎng)景下,zprofile用戶和筆記信息都存儲(chǔ)在HBase。為了保證集群的數(shù)據(jù)安全和服務(wù)穩(wěn)定性,HBase采用了雙集群部署,寫入和讀取方通過(guò)HBase Client API做數(shù)據(jù)存儲(chǔ)。HBase的用戶數(shù)據(jù)在數(shù)十TB,在百萬(wàn)QPS下,P99時(shí)延已經(jīng)在70ms左右,隨著QPS的快速增長(zhǎng),時(shí)延越來(lái)越高,集群擴(kuò)容帶來(lái)的存儲(chǔ)成本也越來(lái)越高,穩(wěn)定性保障也面臨極大的挑戰(zhàn)。

RedKV1.0上線后,經(jīng)過(guò)半年多的打磨,開始慢慢承接公司的核心業(yè)務(wù)。推薦平臺(tái)架構(gòu)組也開始著手打造zprofile中臺(tái)服務(wù),收斂上下游的業(yè)務(wù),提供標(biāo)準(zhǔn)統(tǒng)一的讀寫方式。在存儲(chǔ)方案上,平臺(tái)架構(gòu)組同學(xué)和存儲(chǔ)組經(jīng)過(guò)多次的業(yè)務(wù)溝通,最終選擇使用RedKV作為底層存儲(chǔ),主要對(duì)接兩類業(yè)務(wù)方:分別是數(shù)據(jù)生產(chǎn)者 producer 以及數(shù)據(jù)消費(fèi)方 consumer。zprofile最終的中臺(tái)架構(gòu)如下圖15:

  • zprofile-write service 對(duì)上游提供統(tǒng)一的數(shù)據(jù)寫入接口服務(wù),提供用戶和比較的Meta管理,用戶數(shù)據(jù)寫入redkv-zprofile-user集群,筆記及其他數(shù)據(jù)寫入redkv-zprofile-other集群。
  • zprofile-service對(duì)下游提供統(tǒng)一的數(shù)據(jù)消費(fèi)服務(wù),對(duì)應(yīng)時(shí)延要求不高的離線服務(wù),RedKV本身支持單向數(shù)據(jù)復(fù)制的能力通過(guò)2個(gè)offline小集群提供數(shù)據(jù)scan業(yè)務(wù)。

整體架構(gòu)改造完成后,使用RedKV對(duì)接同樣QPS的業(yè)務(wù)能力,成本節(jié)省了36%, P99性能提升了約5倍。

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

圖15. zprofile中臺(tái)

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

[1] Pinterest 數(shù)據(jù)復(fù)制:

https://medium.com/pinterest-engineering/open-sourcing-rocksplicator-a-real-time-rocksdb-data-replicator-558cd3847a9d

[2] Rocskdb:

https://github.com/facebook/rocksdb/wiki

[3] HeavyKeeper:

HeavyKeeper: An Accurate Algorithm for Finding Top-k Elephant Flows | USENIX

小紅書如何保存視頻無(wú)水印,小紅書怎樣保存無(wú)水印視頻?

云哲

小紅書基礎(chǔ)架構(gòu)存儲(chǔ)組,目前主要負(fù)責(zé)RedKV1.0架構(gòu)下的功能開發(fā)和穩(wěn)定性建設(shè),研究方向?yàn)榉植际終V、持久化內(nèi)存KV存儲(chǔ)和表格存儲(chǔ)。

久美

小紅書基礎(chǔ)架構(gòu)存儲(chǔ)組,目前主要負(fù)責(zé)RedKV2.0架構(gòu)下的功能開發(fā)和存儲(chǔ)中間件建設(shè),研究研究方向?yàn)榉植际終V和存儲(chǔ)中間件。

文書

小紅書基礎(chǔ)架構(gòu)存儲(chǔ)組,目前主要負(fù)責(zé)RedKV1.0架構(gòu)下的功能開發(fā)和跨云多活建設(shè),研究方向?yàn)榉植际終V和存儲(chǔ)中間件。

來(lái)源:微信公眾號(hào):小紅書技術(shù)REDtech

出處:https://mp.weixin.qq.com/s/ES9cFTJxw058Ktb66NmKYA

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 sumchina520@foxmail.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。

相關(guān)新聞

聯(lián)系我們

聯(lián)系我們

400-9010-860

在線咨詢:點(diǎn)擊這里給我發(fā)消息

微信:85018612

商夢(mèng)建站客服

工作時(shí)間:周一至周六

9:00-18:30,節(jié)假日休息

關(guān)注微信
關(guān)注微信
分享本頁(yè)
返回頂部