Tair持久存储系列技术解读
簡(jiǎn)介:?阿里云數(shù)據(jù)庫(kù)重磅發(fā)布自研Tair持久存儲(chǔ)系列的產(chǎn)品打破了傳統(tǒng)Redis中的數(shù)據(jù)只能在易失性存儲(chǔ)上進(jìn)行讀寫(xiě)的刻板印象,針對(duì)客戶不同業(yè)務(wù)階段的數(shù)據(jù)存儲(chǔ)要求與服務(wù)成本考量,全新實(shí)現(xiàn)了持久性更強(qiáng)、成本更低的KV數(shù)據(jù)庫(kù)。
Redis做為當(dāng)今主流的內(nèi)存數(shù)據(jù)庫(kù)支持許多豐富的數(shù)據(jù)結(jié)構(gòu),比如哈希表、集合,還有l(wèi)ua腳本、事務(wù)、消息訂閱等等高級(jí)特性,同時(shí)使用內(nèi)存做為主要的存儲(chǔ)介質(zhì),支持高速訪問(wèn)。
但是由于其數(shù)據(jù)全部存儲(chǔ)在內(nèi)存,成本較高,而且對(duì)于海量數(shù)據(jù)存儲(chǔ)的支持也存在一些痛點(diǎn),比如在AOFREWRITE和生成RDB快照時(shí)會(huì)有較高的latency spike,大數(shù)據(jù)量下全量同步耗時(shí)較長(zhǎng)、失敗率較高。并且數(shù)據(jù)可靠性稍弱,RDB和AOF不能保證數(shù)據(jù)不丟失。
為了解決上述問(wèn)題,拓寬Redis的應(yīng)用場(chǎng)景,我們結(jié)合新技術(shù)新硬件推出了Tair持久存儲(chǔ)系列產(chǎn)品:容量存儲(chǔ)型和持久內(nèi)存型,支持大容量存儲(chǔ)和更高的數(shù)據(jù)可靠性。
>>發(fā)布會(huì)傳送門
點(diǎn)擊了解產(chǎn)品詳情
容量存儲(chǔ)型
使用磁盤(pán)存儲(chǔ)就是其中的解決方案之一,利用磁盤(pán)可以降低成本并且提供海量存儲(chǔ)。但是在磁盤(pán)上實(shí)現(xiàn)redis也會(huì)有一些挑戰(zhàn):
1.首先redis的數(shù)據(jù)結(jié)構(gòu)都是基于內(nèi)存實(shí)現(xiàn),內(nèi)存可以直接尋址,而磁盤(pán)是個(gè)塊設(shè)備,需要在磁盤(pán)上構(gòu)建存儲(chǔ)引擎來(lái)支持redis數(shù)據(jù)結(jié)構(gòu)訪問(wèn)。
2.另外磁盤(pán)和內(nèi)存有較大的性能差距,原生redis單線程的架構(gòu)無(wú)法滿足吞吐需求,需要從架構(gòu)設(shè)計(jì)上提升訪問(wèn)性能。
應(yīng)對(duì)這些挑戰(zhàn),我們基于rocksdb進(jìn)行了改造,提供了高性能的存儲(chǔ)引擎TairDB,并實(shí)現(xiàn)了redis數(shù)據(jù)結(jié)構(gòu)向簡(jiǎn)單kv的編碼映射,使redis數(shù)據(jù)能夠存儲(chǔ)在磁盤(pán)上;采用多線程的架構(gòu)來(lái)提升訪問(wèn)磁盤(pán)的性能;同時(shí)使用阿里云ESSD高效云盤(pán)為存儲(chǔ)底座,利用云盤(pán)快照進(jìn)行備份和全量同步,避免fork帶來(lái)的問(wèn)題并提高全量同步效率。
redis有五種基本數(shù)據(jù)類型,其中string可以直接映射到rocksdb的kv,但是其他一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu)hash、list、set、zset需要通過(guò)一定格式的編碼把redis的數(shù)據(jù)結(jié)構(gòu)映射到rocksd的kv上。
我們把redis數(shù)據(jù)結(jié)構(gòu)拆分為meta和data兩類,進(jìn)行不同的編碼,通過(guò)meta可以去找到其對(duì)應(yīng)的data,也即二級(jí)索引。
以hash為例,執(zhí)行hset myhash myfield myvalue之后,hash表的名字myhash就會(huì)在meta中生成一份kv,其中key就是myhash,value會(huì)標(biāo)志它的屬性為hash表;myfield和myvalue會(huì)記錄在data中,再以key+類型+filed就可以索引到hash表的所有內(nèi)容。
為了實(shí)現(xiàn)多線程架構(gòu),首先需要解決key沖突的問(wèn)題,這里我們實(shí)現(xiàn)了key級(jí)別的鎖,這樣可以大大降低鎖沖突,提高并發(fā)度。命令執(zhí)行過(guò)程中多個(gè)線程首先獲取key鎖,然后按命令的邏輯執(zhí)行,通過(guò)預(yù)先設(shè)計(jì)好的編碼規(guī)則存取數(shù)據(jù)。最后再把結(jié)果以事務(wù)的方式提交給底層存儲(chǔ)引擎。每個(gè)命令的執(zhí)行都是要在事務(wù)提交之后才會(huì)返回結(jié)果,這樣每一條命令都是持久化的,大大提升了數(shù)據(jù)可靠性。
關(guān)于主備復(fù)制,全量復(fù)制使用云盤(pán)快照提高效率。增量復(fù)制采用類似MySQL binlog的方式,事務(wù)提交之后同時(shí)也會(huì)寫(xiě)入binlog,然后會(huì)有sender把binlog傳輸給備庫(kù),binlog傳輸?shù)絺鋷?kù)上時(shí)會(huì)首先保存為relaylog作為中繼,然后通過(guò)relaylog再回放應(yīng)用,這樣有兩點(diǎn)好處:
1.支持semisync,只要relaylog落盤(pán)就可以認(rèn)為事務(wù)在備庫(kù)也提交完成,不用等待relaylog應(yīng)用,這樣既可以提升增量同步的效率,同時(shí)提供了更強(qiáng)的主備一致性保證。
2.支持并發(fā)回放,在relaylog中記錄并發(fā)度的元信息,不同的key就可以進(jìn)行并發(fā)回放提高效率,同時(shí)相同的key仍然按序回放,保證主備一致性,不會(huì)造成數(shù)據(jù)錯(cuò)亂。
上圖為不同類型場(chǎng)景和實(shí)例規(guī)格下的性能測(cè)試結(jié)果,測(cè)試命令為時(shí)間復(fù)雜度O(1)的GET/SET,綜合性能中位數(shù)在開(kāi)源版70%。
在數(shù)據(jù)小于內(nèi)存的情況下大部分?jǐn)?shù)據(jù)都會(huì)緩存在操作系統(tǒng)的page cache中,整體性能會(huì)優(yōu)于數(shù)據(jù)大于內(nèi)存的情況。規(guī)格越高的實(shí)例線程越多并發(fā)度也就越高,性能也相對(duì)越好。另外不同于內(nèi)存中的GET/SET,磁盤(pán)上寫(xiě)入數(shù)據(jù)需要有read modify write的過(guò)程,也即需要先讀取元數(shù)據(jù)才能進(jìn)行修改,所以對(duì)于GET/SET寫(xiě)性能要弱于讀性能。
持久內(nèi)存型
傲騰持久內(nèi)存是Intel推出的一款非易失性內(nèi)存產(chǎn)品,在提供接近內(nèi)存延時(shí)能力的同時(shí)保持持久化的能力, 理想情況下對(duì)于Redis場(chǎng)景來(lái)說(shuō)是非常好的,因?yàn)閿?shù)據(jù)寫(xiě)入到持久內(nèi)存中已經(jīng)持久化,那么就不需要額外的日志和Checkpoint用來(lái)保證持久化的特性,同時(shí)傲騰持久內(nèi)存在延遲上也比較接近內(nèi)存優(yōu)于傳統(tǒng)SSD,成本上對(duì)比內(nèi)存也更加的便宜。
Redis基于傲騰持久內(nèi)存能達(dá)到高性能的同時(shí)擁有較高的持久化能力,但是實(shí)際在工程實(shí)現(xiàn)會(huì)碰到非常大的挑戰(zhàn),包括:
1.需要使用持久化內(nèi)存的分配器來(lái)代替原有的內(nèi)存分配器,分配器的元數(shù)據(jù)信息需要持久化,否則在恢復(fù)的時(shí)候會(huì)造成內(nèi)存的泄露或者不一致。
2.原本String,Set,Hash這些數(shù)據(jù)結(jié)構(gòu)和索引在異常的時(shí)候全部失效在恢復(fù)的時(shí)候重建,而現(xiàn)在這些數(shù)據(jù)都是持久化的,如何支持設(shè)計(jì)持久化的數(shù)據(jù)結(jié)構(gòu)是目前工業(yè)界和理論界主要的研究方向之一
3.索引和數(shù)據(jù)的一致性,數(shù)據(jù)的完整性,這些都會(huì)在下一張NVM的挑戰(zhàn)中做更詳細(xì)的闡釋
4.持久內(nèi)存在延時(shí)還是比內(nèi)存更高,如何做好冷熱分離,讓系統(tǒng)擁有更高的性能。
5.如何擁有高性能的同時(shí)兼?zhèn)鋸?qiáng)大的持久化能力。
持久內(nèi)存的使用分為兩大類Memory Mode和 AppDirecrt Mode, memory mode無(wú)需用戶改造但是沒(méi)有持久化內(nèi)里, 使用App Direct mode之后對(duì)比傳統(tǒng)SSD從block尋址轉(zhuǎn)為字節(jié)尋址,同時(shí)接口也從文件write/read轉(zhuǎn)為內(nèi)存的load和store。
數(shù)據(jù)寫(xiě)入內(nèi)存的過(guò)程可能會(huì)停留在CPU L1,L2cache,需要調(diào)用類似CLWB和CLFLUSHOPT這樣的指令來(lái)刷到內(nèi)存系統(tǒng)中,由于CPU只能保證8個(gè)字節(jié)的原子寫(xiě)入,那么對(duì)于一個(gè)16字節(jié)的寫(xiě)很有可能在寫(xiě)完第一個(gè)8字節(jié)的時(shí)候crash,后半部分沒(méi)有寫(xiě)入成功這個(gè)就是所謂的partial writes, 上層應(yīng)用在使用持久內(nèi)存的時(shí)候需要額外的實(shí)現(xiàn)來(lái)保障數(shù)據(jù)持久問(wèn)題。
下面的例子是一個(gè)雙向鏈表,傳統(tǒng)內(nèi)存crash之后所有的數(shù)據(jù)丟失,而持久內(nèi)存則保留了crash的狀態(tài),因此會(huì)出現(xiàn)B的Next指針指向了C而C的Prev指針缺沒(méi)有指向B,這個(gè)時(shí)候的雙向鏈表是出于異常的狀態(tài)。 從鏈表衍生開(kāi)來(lái)內(nèi)存分配器中的管理結(jié)構(gòu)也存在這個(gè)問(wèn)題,會(huì)出現(xiàn)內(nèi)存泄露等情況。
由于持久化的挑戰(zhàn),目前主流使用持久內(nèi)存的方式都是當(dāng)做Memory或者使用AppDirect但是不支持持久化,阿里云Tair持久內(nèi)存版的是基于傲騰持久內(nèi)存的自研引擎,解決了持久化編程中遇到的各種挑戰(zhàn),撘配阿里云官方提供的Linux操作系統(tǒng)鏡像Aliyun Linux,Aliyun彈性計(jì)算服務(wù)首次(全球首家)在神龍裸金屬服務(wù)器上引入傲騰持久內(nèi)存,深度優(yōu)化完善支持,為客戶提供安全、穩(wěn)定、高性能的體驗(yàn)。
阿里云持久內(nèi)存版Tair的每一條記錄都確保寫(xiě)入AEP并且持久化才返回,極大的提升數(shù)據(jù)的可靠性, 同時(shí)在讀取路徑上使用Dram緩存如索引等熱點(diǎn)數(shù)據(jù)結(jié)構(gòu)和元數(shù)信息,來(lái)加速數(shù)據(jù)訪問(wèn)的存取。
在神龍裸金屬機(jī)器上,我們使用相同配置進(jìn)行了Tair持久內(nèi)存版和Redis6.0的性能對(duì)比, 整體上吞吐為社區(qū)內(nèi)存版本的90%, 延時(shí)上由于沒(méi)有AofRewrite的干擾,P95的延時(shí)更加的穩(wěn)定。
?
?
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的Tair持久存储系列技术解读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 高可用的本质
- 下一篇: 深入理解C++中的RVO