本次分享主題
pika 是360 DBA和基礎(chǔ)架構(gòu)組聯(lián)合開發(fā)的類redis 存儲系統(tǒng), 完全支持Redis協(xié)議,用戶不需要修改任何代碼, 就可以將服務(wù)遷移至pika. 有維護(hù)redis 經(jīng)驗的DBA 維護(hù)pika 不需要學(xué)習(xí)成本
pika 主要解決的是用戶使用redis的內(nèi)存大小超過50G, 80G 等等這樣的情況, 會遇到比如啟動恢復(fù)時間長, 一主多從代價大, 硬件成本貴, 緩沖區(qū)容易寫滿等等問題. pika 就下針對這些場景的一個解決方案
pika 目前已經(jīng)開源, github地址:
https://github.com/Qihoo360/pika
重點(diǎn):
- pika 的單線程的性能肯定不如redis, pika是多線程的結(jié)構(gòu), 因此在線程數(shù)比較多的情況下, 某些數(shù)據(jù)結(jié)構(gòu)的性能可以優(yōu)于redis
- pika 肯定不是完全優(yōu)于redis 的方案, 只是在某些場景下面更適合. 所以目前公司內(nèi)部redis, pika 是共同存在的方案, DBA會根據(jù)業(yè)務(wù)的場景挑選合適的方案
本次分享分成4個部分
- 大容量redis 容易遇到的問題
- pika 整體架構(gòu)
- pika 具體實現(xiàn)
- pika vs redis
背景
redis 提供了豐富的多數(shù)據(jù)結(jié)構(gòu)的接口, 在redis 之前, 比如memcache 都認(rèn)為后端只需要存儲kv的結(jié)構(gòu)就可以, 不需要感知這個value 里面的內(nèi)容. 用戶需要使用的話通過json_encode, json_decode 等形式進(jìn)行數(shù)據(jù)的讀取就行. 但是其實redis 類似做了一個微創(chuàng)新, redis 提供了多數(shù)據(jù)結(jié)構(gòu)的支持, 讓前端寫代碼起來更加的方便了
因此redis 在公司的使用率也是越來越廣泛, 用戶不知不覺把越來越多的數(shù)據(jù)存儲在redis中, 隨著用戶的使用, DBA 發(fā)現(xiàn)有些redis 實例的大小也是越來越大. 在redis 實例內(nèi)存使用比較大的情況下, 遇到的問題也會越來越多, 因此DBA和我們一起實現(xiàn)了大容量redis 的解決方案
最近半年公司每天redis 的訪問情況
redis 架構(gòu)方案
大容量redis 遇到的問題
- 恢復(fù)時間長
我們線上的redis 一般同時開啟rdb 和 aof.
我們知道aof的作用是實時的記錄用戶的寫入操作, rdb 是redis 某一時刻數(shù)據(jù)的完整快照. 那么恢復(fù)的時候一般是通過 rdb + aof 的方式進(jìn)行恢復(fù), 根據(jù)我們線上的情況 50G redis 恢復(fù)時間需要差不多70分鐘
- 一主多從, 主從切換代價大
redis 在主庫掛掉以后, 從庫升級為新的主庫. 那么切換主庫以后, 所有的從庫都需要跟新主做一次全同步, 全量同步一次大容量的redis, 代價非常大.
- 緩沖區(qū)寫滿問題
為了防止同步緩沖區(qū)被復(fù)寫隘梨,dba給redis設(shè)置了2G的巨大同步緩沖區(qū),這對于內(nèi)存資源來講代價很大. 當(dāng)由于機(jī)房之間網(wǎng)絡(luò)有故障, 主從同步出現(xiàn)延遲了大于2G以后, 就會觸發(fā)全同步的過程. 如果多個從庫同時觸發(fā)全同步的過程, 那么很容易就將主庫給拖死
- 內(nèi)存太貴
我們一般線上使用的redis 機(jī)器是 64G, 96G. 我們只會使用80% 的空間.
如果一個redis 的實例是50G, 那么基本一臺機(jī)器只能運(yùn)行一個redis 實例. 因此特別的浪費(fèi)資源
總結(jié): 可以看到在redis 比較小的情況下, 這些問題都不是問題, 但是當(dāng)redis 容量上去以后. 很多操作需要的時間也就越來越長了
pika 整體架構(gòu)
主要組成:
- 網(wǎng)絡(luò)模塊 pink
- 線程模塊
- 存儲引擎 nemo
- 日志模塊 binlog
pink 網(wǎng)絡(luò)模塊
- 基礎(chǔ)架構(gòu)團(tuán)隊開發(fā)網(wǎng)絡(luò)編程庫, 支持pb, redis等等協(xié)議. 對網(wǎng)絡(luò)編程的封裝, 用戶實現(xiàn)一個高性能的server 只需要實現(xiàn)對應(yīng)的DealMessage() 函數(shù)即可
- 支持單線程模型, 多線程worker模型
- github 地址: https://github.com/baotiao/pink
線程模塊
pika 基于pink 對線程進(jìn)行封裝. 使用多個工作線程來進(jìn)行讀寫操作矛渴,由底層nemo引擎來保證線程安全,線程分為11種:
PikaServer:主線程
DispatchThread:監(jiān)聽端口1個端口,接收用戶連接請求
ClientWorker:存在多個(用戶配置)较沪,每個線程里有若干個用戶客戶端的連接控轿,負(fù)責(zé)接收處理用戶命令并返回結(jié)果,每個線程執(zhí)行寫命令后,追加到binlog中
Trysync:嘗試與master建立首次連接刚梭,并在以后出現(xiàn)故障后發(fā)起重連
ReplicaSender:存在多個(動態(tài)創(chuàng)建銷毀衅金,本master節(jié)點(diǎn)掛多少個slave節(jié)點(diǎn)就有多少個)您觉,每個線程根據(jù)slave節(jié)點(diǎn)發(fā)來的同步偏移量般堆,從binlog指定的偏移開始實時同步命令給slave節(jié)點(diǎn)
ReplicaReceiver:存在1個(動態(tài)創(chuàng)建銷毀淮摔,一個slave節(jié)點(diǎn)同時只能有一個master)造垛,將用戶指定或當(dāng)前的偏移量發(fā)送給master節(jié)點(diǎn)并開始接收執(zhí)行master實時發(fā)來的同步命令杆逗,在本地使用和master完全一致的偏移量來追加binlog
SlavePing:slave用來向master發(fā)送心跳進(jìn)行存活檢測
HeartBeat:master用來接收所有slave發(fā)送來的心跳并恢復(fù)進(jìn)行存活檢測
bgsave:后臺dump線程
scan:后臺掃描keyspace線程
purge:后臺刪除binlog線程
存儲引擎 nemo
- Pika 的存儲引擎, 基于Rocksdb 修改. 封裝Hash, List, Set, Zset等數(shù)據(jù)結(jié)構(gòu)
我們知道redis 是需要支持多數(shù)據(jù)結(jié)構(gòu)的, 而rocksdb 只是一個kv的接口, 那么我們?nèi)绾螌崿F(xiàn)的呢?
比如對于Hash 數(shù)據(jù)結(jié)構(gòu):
對于每一個Hash存儲悔橄,它包括hash鍵(key)争舞,hash鍵下的域名(field)和存儲的值 (value).
nemo的存儲方式是將key和field組合成為一個新的key床牧,將這個新生成的key與所要存儲的value組成最終落盤的kv鍵值對。同時删铃,對于每一個hash鍵顷蟆,nemo還為它添加了一個存儲元信息的落盤kv风题,它保存的是對應(yīng)hash鍵下的所有域值對的個數(shù)。
每個hash鍵、field蹦玫、value到落盤kv的映射轉(zhuǎn)換
每個hash鍵的元信息的落盤kv的存儲格式
比如對于List 數(shù)據(jù)結(jié)構(gòu):
顧名思義,每個List結(jié)構(gòu)的底層存儲也是采用鏈表結(jié)構(gòu)來完成的猖任。對于每個List鍵,它的每個元素都落盤為一個kv鍵值對纽甘,作為一個鏈表的一個節(jié)點(diǎn),稱為元素節(jié)點(diǎn)锌杀。和hash一樣,每個List鍵也擁有自己的元信息漩蟆。
每個元素節(jié)點(diǎn)對應(yīng)的落盤kv存儲格式
每個元信息的落盤kv的存儲格式
其他的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的方式也類似, 通過將hash_filed 拼成一個key, 存儲到支持kv的rocksdb 里面去. 從而實現(xiàn)多數(shù)據(jù)結(jié)構(gòu)的結(jié)構(gòu)
日志模塊 binlog
Pika的主從同步是使用Binlog來完成的.
binlog 本質(zhì)是順序?qū)懳募? 通過Index + offset 進(jìn)行同步點(diǎn)檢查.
解決了同步緩沖區(qū)太小的問題
支持全同步 + 增量同步
master 執(zhí)行完一條寫命令就將命令追加到Binlog中,ReplicaSender將這條命令從Binlog中讀出來發(fā)送給slave森篷,slave的ReplicaReceiver收到該命令剪验,執(zhí)行,并追加到自己的Binlog中.
當(dāng)發(fā)生主從切換以后, slave僅需要將自己當(dāng)前的Binlog Index + offset 發(fā)送給master灯萍,master找到后從該偏移量開始同步后續(xù)命令
為了防止讀文件中寫錯一個字節(jié)則導(dǎo)致整個文件不可用,所以pika采用了類似leveldb log的格式來進(jìn)行存儲,具體如下:
主要功能
pika 線上架構(gòu)
主從架構(gòu)
旁白: 為了減少用戶的學(xué)習(xí)成本, 目前pika 的主從同步功能是和redis完全一樣, 只需要slaveof 就可以實現(xiàn)主從關(guān)系的建立, 使用起來非常方便
背景
- Pika Replicate
pika支持master/slave的復(fù)制方式澜共,通過slave端的slaveof命令激發(fā)
salve端處理slaveof命令向叉,將當(dāng)前狀態(tài)變?yōu)閟lave,改變連接狀態(tài)
slave的trysync線程向master發(fā)起trysync嗦董,同時將要同步點(diǎn)傳給master
master處理trysync命令母谎,發(fā)起對slave的同步過程,從同步點(diǎn)開始順序發(fā)送binlog或進(jìn)行全同步
- Binlog
pika同步依賴binlog
binlog文件會自動或手動刪除
當(dāng)同步點(diǎn)對應(yīng)的binlog文件不存在時京革,需要通過全同步進(jìn)行數(shù)據(jù)同步
全同步
-
簡介
需要進(jìn)行全同步時奇唤,master會將db文件dump后發(fā)送給slave
通過rsync的deamon模式實現(xiàn)db文件的傳輸 -
實現(xiàn)邏輯
slave在trysnc前啟動rsync進(jìn)程啟動rsync服務(wù)
master發(fā)現(xiàn)需要全同步時,判斷是否有備份文件可用匹摇,如果沒有先dump一份
master通過rsync向slave發(fā)送dump出的文件
slave用收到的文件替換自己的db
slave用最新的偏移量再次發(fā)起trysnc
完成同步
-
Slave連接狀態(tài)
No Connect:不嘗試成為任何其他節(jié)點(diǎn)的slave
Connect:Slaveof后嘗試成為某個節(jié)點(diǎn)的slave咬扇,發(fā)送trysnc命令和同步點(diǎn)
Connecting:收到master回復(fù)可以slaveof,嘗試跟master建立心跳
Connected: 心跳建立成功
WaitSync:不斷檢測是否DBSync完成廊勃,完成后更新DB并發(fā)起新的slaveof
主從命令同步
上圖1是一個主從同步的一個過程(即根據(jù)主節(jié)點(diǎn)數(shù)據(jù)庫的操作日志懈贺,將主節(jié)點(diǎn)數(shù)據(jù)庫的改變過程順序的映射到從節(jié)點(diǎn)的數(shù)據(jù)庫上),從圖1中可以看出供搀,每一個從節(jié)點(diǎn)在主節(jié)點(diǎn)下都有一個唯一對應(yīng)的BinlogSenderThread隅居。
(為了說明方便钠至,我們定一個“同步命令”的概念葛虐,即會改變數(shù)據(jù)庫的命令,如set棉钧,hset屿脐,lpush等,而get,hget的诵,lindex則不是)
主要模塊的功能:
WorkerThread:接受和處理用戶的命令万栅;
BinlogSenderThread:負(fù)責(zé)順序地向?qū)?yīng)的從節(jié)點(diǎn)發(fā)送在需要同步的命令;
BinlogReceiverModule: 負(fù)責(zé)接受主節(jié)點(diǎn)發(fā)送過來的同步命令
Binglog:用于順序的記錄需要同步的命令
?
主要的工作過程:
1.當(dāng)WorkerThread接收到客戶端的命令西疤,按照執(zhí)行順序烦粒,添加到Binlog里;
2.BinglogSenderThread判斷它所負(fù)責(zé)的從節(jié)點(diǎn)在主節(jié)點(diǎn)的Binlog里是否有需要同步的命令代赁,若有則發(fā)送給從節(jié)點(diǎn)扰她;
3.BinglogReceiverModule模塊則做以下三件事情:
a. 接收主節(jié)點(diǎn)的BinlogSenderThread發(fā)送過來的同步命令;
b. 把接收到的命令應(yīng)用到本地的數(shù)據(jù)上芭碍;
c. 把接收到的命令添加到本地Binlog里
至此徒役,一條命令從主節(jié)點(diǎn)到從節(jié)點(diǎn)的同步過程完成
BinLogReceiverModule的工作過程:
上圖2是BinLogReceiverModule(在源代碼中沒有這個對象彬祖,這里是為了說明方便谷遂,抽象出來的)的組成,從圖2中可以看出BinlogReceiverModule由一個BinlogReceiverThread和多個BinlogBGWorker組成贰剥。
BinlogReceiverThread: 負(fù)責(zé)接受由主節(jié)點(diǎn)傳送過來的命令瞻讽,并分發(fā)給各個BinlogBGWorker鸳吸,若當(dāng)前的節(jié)點(diǎn)是只讀狀態(tài)(不能接受客戶端的同步命令),則在這個階段寫B(tài)inlog
BinlogBGWorker:負(fù)責(zé)執(zhí)行同步命令速勇;若該節(jié)點(diǎn)不是只讀狀態(tài)(還能接受客戶端的同步命令)层释,則在這個階段寫B(tài)inlog(在命令執(zhí)行之前寫)
BinlogReceiverThread接收到一個同步命令后,它會給這個命令賦予一個唯一的序列號(這個序列號是遞增的)快集,并把它分發(fā)給一個BinlogBGWorker贡羔;而各個BinlogBGWorker則會根據(jù)各個命令的所對應(yīng)的序列號的順序來執(zhí)行各個命令,這樣也就保證了命令執(zhí)行的順序和主節(jié)點(diǎn)執(zhí)行的順序一致了
之所以這么設(shè)計主要原因是:
a. 配備多個BinlogBGWorker是可以提高主從同步的效率个初,減少主從同步的滯后延遲乖寒;
b. 讓BinlogBGWorker在執(zhí)行執(zhí)行之前寫B(tài)inlog可以提高命令執(zhí)行的并行度;
c. 在當(dāng)前節(jié)點(diǎn)是非只讀狀態(tài)院溺,讓BinglogReceiverThread來寫B(tài)inlog楣嘁,是為了讓Binglog里保存的命令順序和命令的執(zhí)行順序保持一致;
數(shù)據(jù)備份
不同于Redis珍逸,Pika的數(shù)據(jù)主要存儲在磁盤中逐虚,這就使得其在做數(shù)據(jù)備份時有天然的優(yōu)勢,可以直接通過文件拷貝實現(xiàn)
流程:
打快照:阻寫谆膳,并在這個過程中或的快照內(nèi)容
異步線程拷貝文件:通過修改Rocksdb提供的BackupEngine拷貝快照中文件叭爱,這個過程中會阻止文件的刪除
快照內(nèi)容
當(dāng)前db的所有文件名
manifest文件大小
sequence_number
同步點(diǎn): binlog index + offset
?
秒刪大量的key
在我們大量的使用場景中. 對于Hash, zset, set, list這幾種多數(shù)據(jù)機(jī)構(gòu),當(dāng)member或者field很多的時候漱病,用戶有批量刪除某一個key的需求, 那么這個時候?qū)嶋H刪除的就是rocksdb 底下大量的kv結(jié)構(gòu), 如果只是單純暴力的進(jìn)行刪key操作, 那時間肯定非常的慢, 難以接受. 那我們?nèi)绾慰焖賱h除key买雾?
剛才的nemo 的實現(xiàn)里面我們可以看到, 我們在value 里面增加了version, ttl 字段, 這兩個字段就是做這個事情.
Solution 0:暴力刪除每一個member把曼,時間復(fù)雜度O(m) , m是member的個數(shù);
優(yōu)點(diǎn):易實現(xiàn)漓穿;
缺點(diǎn):同步處理嗤军,會阻礙請求;
Solution 1: 啟動后臺線程晃危,維護(hù)刪除隊列叙赚,執(zhí)行刪除,時間復(fù)雜度O(m)
優(yōu)點(diǎn):不會明顯阻住server僚饭;
缺點(diǎn):仍然要O(m)去刪除members纠俭,可以優(yōu)化刪除的速度;
Redis 是怎么做的浪慌?
舊版本的Del接口冤荆,在實際free大量內(nèi)存的時候仍然會阻塞server;
新版增加了lazy free,根據(jù)當(dāng)前server的負(fù)載权纤,多次動態(tài)free钓简;
Solution 2: 不刪除, 只做標(biāo)記, 時間復(fù)雜度O(1)
優(yōu)點(diǎn):效率就夠了;
缺點(diǎn):需要改動下層rocksdb汹想,一定程度破壞了rocksdb的封裝外邓,各個模塊之間耦合起來;
方案:
Key的元信息增加版本古掏,表示當(dāng)前key的有效版本损话;
操作:
Put:查詢key的最新版本,后綴到val槽唾;
Get:查詢key的最新版本丧枪,過濾最新的數(shù)據(jù);
Iterator: 迭代時庞萍,查詢key的版本拧烦,過濾舊版本數(shù)據(jù);
Compact:數(shù)據(jù)的實際刪除是在Compact過程中钝计,根據(jù)版本信息過濾恋博;
目前nemo 采用的就是第二種, 通過對rocksdb 的修改, 可以實現(xiàn)秒刪的功能, 后續(xù)通過修改rocksdb compact的實現(xiàn), 在compact 的過程中, 將歷史的數(shù)據(jù)淘汰掉
數(shù)據(jù)compact 策略
rocksdb 的compact 策略是在寫放大, 讀放大, 空間放大的權(quán)衡.
那么我們DBA經(jīng)常會存在需求盡可能減少空間的使用, 因此DBA希望能夠隨時觸發(fā)手動compact, 而又盡可能的不影響線上的使用, 而rocksdb 默認(rèn)的手動compact 策略是最高優(yōu)先級的, 會阻塞線上的正常流程的合并.
rocksdb 默認(rèn)的 manual compact 的限制
a) 當(dāng)manual compact執(zhí)行時,會等待所有的自動compact任務(wù)結(jié)束, 然后才會執(zhí)行本次manual compact私恬;
b) manual執(zhí)行期間债沮,自動compact無法執(zhí)行
- 當(dāng)manual執(zhí)行很長時間,無法執(zhí)行自動compact本鸣,導(dǎo)致線上新的寫請求只能在memtable中疫衩;
- 當(dāng)memtable個數(shù)超過設(shè)置的level0_slowdown_writes_trigger(默認(rèn)20),寫請求會出被sleep永高;
- 再嚴(yán)重一些隧土,當(dāng)超過level0_stop_writes_trigger(默認(rèn)24)提针,完全停寫命爬;
為了避免這種情況曹傀,我們對compact的策略進(jìn)行調(diào)整,使得自動compact一直優(yōu)先執(zhí)行饲宛,避免停寫皆愉;
總結(jié):
- 恢復(fù)時間長
pika 的存儲引擎是nemo, nemo 使用的是rocksdb, 我們知道 rocksdb 啟動不需要加載全部數(shù)據(jù), 只需要加載幾M的log 文件就可以啟動, 因此恢復(fù)時間非常快 - 一主多從, 主從切換代價大
在主從切換的時候, 新主確定以后, 從庫會用當(dāng)前的偏移量嘗試與新主做一次部分同步, 如果部分同步不成功才做全同步. 這樣盡可能的減少全同步次數(shù) - 緩沖區(qū)寫滿問題
pika 不適用內(nèi)存buffer 進(jìn)行數(shù)據(jù)同步, pika 的主從同步的操作記錄在本地的binlog 上, binlog 會隨著操作的增長進(jìn)行rotate操作. 因此不會出現(xiàn)把緩沖區(qū)寫滿的問題 - 內(nèi)存昂貴問題
pika 的存儲引擎nemo 使用的是rocksdb, rocksdb 和同時使用內(nèi)存和磁盤減少對內(nèi)存的依賴. 同時我們盡可能使用SSD盤來存放數(shù)據(jù), 盡可能跟上redis 的性能.
pika vs redis
pika相對于redis艇抠,最大的不同就是pika是持久化存儲幕庐,數(shù)據(jù)存在磁盤上,而redis是內(nèi)存存儲家淤,由此不同也給pika帶來了相對于redis的優(yōu)勢和劣勢
優(yōu)勢:
- 容量大:Pika沒有Redis的內(nèi)存限制, 最大使用空間等于磁盤空間的大小
- 加載db速度快:Pika 在寫入的時候, 數(shù)據(jù)是落盤的, 所以即使節(jié)點(diǎn)掛了, 不需要rbd或者aof异剥,pika 重啟不用重新加載數(shù)據(jù)到內(nèi)存而是直接使用已經(jīng)持久化在磁盤上的數(shù)據(jù), 不需要任何數(shù)據(jù)回放操作,這大大降低了重啟成本絮重。
- 備份速度快:Pika備份的速度大致等同于cp的速度(拷貝數(shù)據(jù)文件后還有一個快照的恢復(fù)過程冤寿,會花費(fèi)一些時間),這樣在對于百G大庫的備份是快捷的青伤,更快的備份速度更好的解決了主從的全同步問題
劣勢:
由于Pika是基于內(nèi)存和文件來存放數(shù)據(jù), 所以性能肯定比Redis低一些, 但是我們一般使用SSD盤來存放數(shù)據(jù), 盡可能跟上Redis的性能督怜。
總結(jié):
從以上的對比可以看出, 如果你的業(yè)務(wù)場景的數(shù)據(jù)比較大,Redis 很難支撐狠角, 比如大于50G号杠,或者你的數(shù)據(jù)很重要,不允許斷電丟失丰歌,那么使用Pika 就可以解決你的問題姨蟋。
而在實際使用中,大多數(shù)場景下pika的性能大約是Redis的50%~80%立帖,在某些特定場景下芬探,例如range 500,pika的性能只有redis的20%厘惦,針對這些場景我們?nèi)匀辉诟倪M(jìn)
在360內(nèi)部使用情況:
粗略的統(tǒng)計如下:
當(dāng)前每天承載的總請求量超過100億, 實例數(shù)超過100個
當(dāng)前承載的數(shù)據(jù)總量約3 TB
性能對比
Server Info:
CPU: 24 Cores, Intel(R) Xeon(R) CPU E5-2630 v2 @ 2.60GHz
MEM: 165157944 kB
OS: CentOS release 6.2 (Final)
NETWORK CARD: Intel Corporation I350 Gigabit Network Connection
測試過程, 在pika 中先寫入150G 大小的數(shù)據(jù). 寫入Hash key 50個, field 1千萬級別.
redis 寫入5G 大小的數(shù)據(jù)
?
Pika:
18個線程
redis:
單線程
結(jié)論: pika 的單線程的性能肯定不如redis, pika是多線程的結(jié)構(gòu), 因此在線程數(shù)比較多的情況下, 某些數(shù)據(jù)結(jié)構(gòu)的性能可以優(yōu)于redis
wiki
github 地址:
https://github.com/Qihoo360/pika
github wiki:
https://github.com/Qihoo360/pika/wiki/pika介紹
FAQ
- 如果我們想使用新DB, 那核心問題是如何進(jìn)行數(shù)據(jù)遷移. 從redis遷移到pika需要經(jīng)過幾個步驟偷仿?
開發(fā)需要做的:
開發(fā)不需要做任何事,不用改代碼宵蕉、不用替換driver(pika使用原生redis的driver)酝静,什么都不用動,看dba干活就好
dba需要做的:
1.dba遷移redis數(shù)據(jù)到pika
2.dba將redis的數(shù)據(jù)實時同步到pika羡玛,確保redis與pika的數(shù)據(jù)始終一致
3.dba切換lvs后端ip别智,由pika替換redis
遷移過程中需要停業(yè)務(wù)/業(yè)務(wù)會受到影響嗎:
然而并不會
遷移是無縫且溫和的嗎:
那當(dāng)然
?
- 這個和你們公司內(nèi)部的bada 有什么區(qū)別?
我們之前在bada 上面支持過redis 的多數(shù)據(jù)結(jié)構(gòu), 并且兼容redis協(xié)議, 但是遇到了問題.
在分布式系統(tǒng)里面, 對key 的hash 場景的通常是兩種方案:
- 以BigTable 為代表的, 支持range key 的hash 方案. 這個方案的好處是可以實現(xiàn)動態(tài)的擴(kuò)展
- 以Dynamo 為代表的, 取模的hash 方案. 這個方案的好處是時間簡單
我們bada 目前支持的是取模的hash 方案, 在實現(xiàn)redis 的多數(shù)據(jù)結(jié)構(gòu)的時候, 比如hash 我們采用key取模找到對應(yīng)的分片. 那么這樣帶來的問題是由于多數(shù)據(jù)結(jié)構(gòu)里面key 不多, field 比較多的場景還是大部分的情況, 因此極容易照成分片的不均勻, 性能退化很明顯.
- 為什么pika 使用多線程而不是像redis 單線程的結(jié)構(gòu)
因為redis 所有的操作都是對于內(nèi)存的操作, 因此理論上redis 的每次操作的時間都不會太長, 因此多線程就可以滿足需求. 而pika 由于涉及到磁盤IO, 你們操作的時間就會長一點(diǎn), 而且IO操作的時間是不均勻的, 因此多線程的效果會更好一些
360基礎(chǔ)架構(gòu)組公眾號: