360開源的類Redis儲存系統:Pika

五柳-先生發表於2016-05-25

Pika 是 360 DBA 和基礎架構組聯合開發的類 Redis 儲存系統,完全支援 Redis 協議,使用者不需要修改任何程式碼,就可以將服務遷移至 Pika。有維護 Redis 經驗的 DBA 維護 Pika 不需要學習成本。

Pika 主要解決的是使用者使用 Redis 的記憶體大小超過 50G、80G 等等這樣的情況,會遇到啟動恢復時間長,一主多從代價大,硬體成本貴,緩衝區容易寫滿等問題。Pika 就是針對這些場景的一個解決方案。

Pika 目前已經開源,github 地址:

https://github.com/Qihoo360/pika

重點

  • Pika 的單執行緒的效能肯定不如 Redis,Pika 是多執行緒的結構,因此線上程數比較多的情況下,某些資料結構的效能可以優於 Redis。

  • Pika 肯定不是完全優於 Redis 的方案,只是在某些場景下面更適合。所以目前公司內部 Redis,Pika 是共同存在的方案。DBA 會根據業務的場景挑選合適的方案。

背景

Redis 提供了豐富的多資料結構的介面,在 Redis 之前,比如 memcache 都認為後端只需要儲存 kv 的結構就可以,不需要感知這個 value 裡面的內容。使用者需要使用的話通過 json_encode,json_decode 等形式進行資料的讀取就行。但是 Redis 做了一個微創新,提供了多資料結構的支援,讓前端寫程式碼起來更加的方便。

因此 Redis 在很多公司的使用率越來越廣泛,使用者不知不覺把越來越多的資料儲存在 Redis 中。隨著使用者的使用,DBA 發現有些 Redis 例項的大小也是越來越大。在 Redis 例項記憶體使用比較大的情況下,遇到的問題也會越來越多,因此 DBA 和我們一起實現了大容量 Redis 的解決方案。

最近半年公司每天 Redis 的訪問情況

首發丨360開源的類Redis儲存系統:Pika

Redis 架構方案

首發丨360開源的類Redis儲存系統:Pika

大容量 Redis 遇到的問題

1. 恢復時間長

我們線上的 Redis 一般同時開啟 rdb 和 aof。

我們知道 aof 的作用是實時的記錄使用者的寫入操作,rdb 是 Redis 某一時刻資料的完整快照。那麼恢復的時候一般是通過 rdb + aof 的方式進行恢復,根據我們線上的情況 50G Redis 恢復時間需要差不多 70 分鐘。

2. 一主多從,主從切換代價大

Redis 在主庫掛掉以後,從庫升級為新的主庫。那麼切換主庫以後,所有的從庫都需要跟新主做一次全同步,全量同步一次大容量的 Redis 代價非常大。

3. 緩衝區寫滿問題

為了防止同步緩衝區被複寫,dba 給 Redis 設定了 2G 的巨大同步緩衝區,這對於記憶體資源來講代價很大。當由於機房之間網路有故障,主從同步出現延遲了大於 2G 以後,就會觸發全同步的過程。如果多個從庫同時觸發全同步的過程, 那麼很容易就將主庫給拖死。

4. 記憶體太貴

我們一般線上使用的 Redis 機器是 64G、96G,我們只會使用 80% 的空間。

如果一個 Redis 的例項是 50G,那麼基本一臺機器只能執行一個 Redis 例項,特別浪費資源。

總結

可以看到在 Redis 比較小的情況下,這些問題都不是問題,但是當 Redis 容量上去以後,很多操作需要的時間也就越來越長了。

Pika 整體架構

首發丨360開源的類Redis儲存系統:Pika

主要組成:

  • 網路模組 pink

  • 執行緒模組

  • 儲存引擎 nemo

  • 日誌模組 binlog

1. pink 網路模組

基礎架構團隊開發網路程式設計庫,支援 pb、Redis 等協議。對網路程式設計的封裝,使用者實現一個高效能的 server 只需要實現對應的 DealMessage 函式即可

支援單執行緒模型、多執行緒 worker 模型。

github 地址:

https://github.com/baotiao/pink

2. 執行緒模組

首發丨360開源的類Redis儲存系統:Pika

Pika 基於 pink 對執行緒進行封裝,使用多個工作執行緒來進行讀寫操作,由底層 nemo 引擎來保證執行緒安全,執行緒分為 11 種:

1) PikaServer:主執行緒

2) DispatchThread:監聽 1 個埠,接收使用者連線請求

3) ClientWorker:存在多個(使用者配置),每個執行緒裡有若干個使用者客戶端的連線,負責接收處理使用者命令並返回結果,每個執行緒執行寫命令後,追加到 binlog 中

4) Trysync:嘗試與 master 建立首次連線,並在以後出現故障後發起重連

5) ReplicaSender:存在多個(動態建立銷燬,本 master 節點掛多少個 slave 節點就有多少個),每個執行緒根據 slave 節點發來的同步偏移量,從 binlog 指定的偏移開始實時同步命令給 slave 節點

6) ReplicaReceiver:存在 1 個(動態建立銷燬,一個 slave 節點同時只能有一個 master),將使用者指定或當前的偏移量傳送給 master 節點並開始接收執行 master 實時發來的同步命令,在本地使用和 master 完全一致的偏移量來追加 binlog

7) SlavePing:slave 用來向 master 傳送心跳進行存活檢測

8) HeartBeat:master 用來接收所有 slave 傳送來的心跳並恢復進行存活檢測

9) bgsave:後臺 dump 執行緒

10) scan:後臺掃描 keyspace 執行緒

11) purge:後臺刪除 binlog 執行緒

3. 儲存引擎 nemo

Pika 的儲存引擎,基於 Rocksdb 修改。封裝 Hash, List, Set, Zset 等資料結構

我們知道 Redis 是需要支援多資料結構,而 rocksdb 只是一個 kv 的介面,那麼我們如何實現的呢?

比如對於 Hash 資料結構:

對於每一個 Hash 儲存,它包括 hash 鍵(key),hash 鍵下的域名(field)和儲存的值(value)。

nemo 的儲存方式是將 key 和 field 組合成為一個新的 key,將這個新生成的 key 與所要儲存的 value 組成最終落盤的 kv 鍵值對。同時,對於每一個 hash 鍵,nemo 還為它新增了一個儲存元資訊的落盤 kv,它儲存的是對應 hash 鍵下的所有域值對的個數。

每個 hash 鍵、field、value到落盤 kv 的對映轉換

首發丨360開源的類Redis儲存系統:Pika

每個 hash 鍵的元資訊的落盤 kv 的儲存格式

首發丨360開源的類Redis儲存系統:Pika

比如對於 List 資料結構:

顧名思義,每個 List 結構的底層儲存也是採用連結串列結構來完成的。對於每個 List 鍵,它的每個元素都落盤為一個 kv 鍵值對,作為一個連結串列的一個節點,稱為元素節點。和 hash 一樣,每個 List 鍵也擁有自己的元資訊。

每個元素節點對應的落盤 kv 儲存格式

首發丨360開源的類Redis儲存系統:Pika

每個元資訊的落盤 kv 的儲存格式

首發丨360開源的類Redis儲存系統:Pika

其他的資料結構實現的方式也類似,通過將 hash_filed 拼成一個 key,儲存到支援 kv 的 RocksDB 裡面去,從而實現多資料結構的結構。

4. 日誌模組 binlog

Pika 的主從同步是使用 Binlog 來完成的;

binlog 本質是順序寫檔案,通過 Index + offset 進行同步點檢查。

解決了同步緩衝區太小的問題;

支援全同步 + 增量同步;

master 執行完一條寫命令就將命令追加到 Binlog 中,ReplicaSender 將這條命令從 Binlog 中讀出來傳送給 slave,slave 的 ReplicaReceiver 收到該命令,執行,並追加到自己的 Binlog 中。

當發生主從切換以後,slave 僅需要將自己當前的 Binlog Index + offset 傳送給 master,master 找到後從該偏移量開始同步後續命令。

為了防止讀檔案中寫錯一個位元組則導致整個檔案不可用,所以Pika採用了類似 leveldb log 的格式來進行儲存,具體如下:

首發丨360開源的類Redis儲存系統:Pika

主要功能

Pika 線上架構

首發丨360開源的類Redis儲存系統:Pika

主從架構

為了減少使用者的學習成本,目前 Pika 的主從同步功能是和 Redis 完全一樣,只需要 slaveof 就可以實現主從關係的建立,使用起來非常方便。

背景

1. Pika Replicate

Pika 支援 master/slave 的複製方式,通過 slave 端的 slaveof 命令激發

salve 端處理 slaveof 命令,將當前狀態變為 slave,改變連線狀態

slave的trysync執行緒向 master 發起 trysync,同時將要同步點傳給 master

master處理trysync命令,發起對slave的同步過程,從同步點開始順序傳送 binlog 或進行全同步

Binlog

Pika 同步依賴 binlog

binlog 檔案會自動或手動刪除

當同步點對應的 binlog 檔案不存在時,需要通過全同步進行資料同步

全同步

簡介

需要進行全同步時,master 會將 db 檔案 dump 後傳送給 slave

通過 rsync 的 deamon 模式實現 db 檔案的傳輸

實現邏輯

  • slave 在 trysnc 前啟動 rsync 程式啟動 rsync 服務;

  • master 發現需要全同步時,判斷是否有備份檔案可用,如果沒有先 dump 一份

  • master 通過 rsync 向 slave 傳送 dump 出的檔案

  • slave 用收到的檔案替換自己的 db

  • slave 用最新的偏移量再次發起 trysnc

  • 完成同步

首發丨360開源的類Redis儲存系統:Pika

Slave 連線狀態

  • No Connect:不嘗試成為任何其他節點的 slave;

  • Connect:Slaveof 後嘗試成為某個節點的 slave,傳送 trysnc 命令和同步點;

  • Connecting:收到 master 回覆可以 slaveof,嘗試跟 master 建立心跳;

  • Connected:心跳建立成功

  • WaitSync:不斷檢測是否 DBSync 完成,完成後更新 DB 併發起新的 slaveof。

首發丨360開源的類Redis儲存系統:Pika

主從命令同步

首發丨360開源的類Redis儲存系統:Pika

上圖1是一個主從同步的一個過程(即根據主節點資料庫的操作日誌,將主節點資料庫的改變過程順序的對映到從節點的資料庫上),從圖中可以看出,每一個從節點在主節點下都有一個唯一對應的 BinlogSenderThread。

為了說明方便,我們定一個“同步命令”的概念,即會改變資料庫的命令,如 set,hset,lpush 等,而 get,hget,lindex 則不是.

主要模組的功能:

1) WorkerThread:接受和處理使用者的命令;

2) BinlogSenderThread:負責順序地向對應的從節點傳送在需要同步的命令;

3) BinlogReceiverModule:負責接受主節點傳送過來的同步命令

4) Binglog:用於順序的記錄需要同步的命令

主要的工作過程:

1.當WorkerThread 接收到客戶端的命令,按照執行順序,新增到 Binlog 裡;

2.BinglogSenderThread 判斷它所負責的從節點在主節點的 Binlog 裡是否有需要同步的命令,若有則傳送給從節點;

3.BinglogReceiverModule 模組則做以下三件事情:

a. 接收主節點的 BinlogSenderThread 傳送過來的同步命令;

b. 把接收到的命令應用到本地的資料上;

c. 把接收到的命令新增到本地 Binlog 裡

至此,一條命令從主節點到從節點的同步過程完成

BinLogReceiverModule 的工作過程:

首發丨360開源的類Redis儲存系統:Pika

上圖是 BinLogReceiverModule(在原始碼中沒有這個物件,這裡是為了說明方便,抽象出來的)的組成,從圖中可以看出 BinlogReceiverModule 由一個 BinlogReceiverThread 和多個 BinlogBGWorker 組成。

BinlogReceiverThread:負責接受由主節點傳送過來的命令,並分發給各個 BinlogBGWorker,若當前的節點是隻讀狀態(不能接受客戶端的同步命令),則在這個階段寫 Binlog

BinlogBGWorker:負責執行同步命令;若該節點不是隻讀狀態(還能接受客戶端的同步命令),則在這個階段寫 Binlog(在命令執行之前寫)

BinlogReceiverThread 接收到一個同步命令後,它會給這個命令賦予一個唯一的序列號(這個序列號是遞增的),並把它分發給一個 BinlogBGWorker;而各個 BinlogBGWorker 則會根據各個命令的所對應的序列號的順序來執行各個命令,這樣也就保證了命令執行的順序和主節點執行的順序一致了

之所以這麼設計主要原因是

  1. 配備多個 BinlogBGWorker 是可以提高主從同步的效率,減少主從同步的滯後延遲;

  2. 讓 BinlogBGWorker 在執行執行之前寫 Binlog 可以提高命令執行的並行度;

  3. 在當前節點是非只讀狀態,讓 BinglogReceiverThread 來寫 Binlog,是為了讓 Binglog 裡儲存的命令順序和命令的執行順序保持一致;

資料備份

不同於 Redis,Pika 的資料主要儲存在磁碟中,這就使得其在做資料備份時有天然的優勢,可以直接通過檔案拷貝實現。

流程:

  • 打快照:阻寫,並在這個過程中或的快照內容;

  • 非同步執行緒拷貝檔案:通過修改 RocksDB 提供的 BackupEngine 拷貝快照中檔案,這個過程中會阻止檔案的刪除。

快照內容

  • 當前 db 的所有檔名

  • manifest 檔案大小

  • sequence_number

  • 同步點:binlog index + offset

首發丨360開源的類Redis儲存系統:Pika

秒刪大量的 key

在我們大量的使用場景中,對於 Hash、zset、set、list 這幾種多資料機構,當 member 或者 field 很多的時候,使用者有批量刪除某一個 key 的需求, 那麼這個時候實際刪除的就是 RocksDB 底下大量的 kv 結構,如果只是單純暴力的進行刪 key 操作,那時間肯定非常的慢,難以接受。那我們如何快速刪除 key?

剛才的 nemo 的實現裡面我們可以看到,我們在 value 裡面增加了 version、ttl 欄位,這兩個欄位就是做這個事情。

Solution 0:暴力刪除每一個 member,時間複雜度O(m) ,m 是 member 的個數;

優點:易實現;

缺點:同步處理,會阻礙請求;

Solution 1:啟動後臺執行緒,維護刪除佇列,執行刪除,時間複雜度 O(m)

優點:不會明顯阻住 server;

缺點:仍然要 O(m) 去刪除 members,可以優化刪除的速度;

Redis 是怎麼做的?

舊版本的Del介面,在實際 free 大量記憶體的時候仍然會阻塞 server;

新版增加了 lazy free,根據當前 server 的負載,多次動態 free;

Solution 2:不刪除,只做標記,時間複雜度 O(1)

優點:效率就夠了;

缺點:需要改動下層 RocksDB,一定程度破壞了 RocksDB 的封裝,各個模組之間耦合起來;

方案:

Key的元資訊增加版本,表示當前 key 的有效版本;

操作:

Put:查詢 key 的最新版本,字尾到 val;

Get:查詢 key 的最新版本,過濾最新的資料;

Iterator: 迭代時,查詢 key 的版本,過濾舊版本資料;


Compact:資料的實際刪除是在 Compact 過程中,根據版本資訊過濾;

目前 nemo 採用的就是第二種,通過對 RocksDB 的修改,可以實現秒刪的功能,後續通過修改 RocksDB compact 的實現,在 compact 的過程中,將歷史的資料淘汰掉。

資料 compact 策略

RoRocksDBcksdb 的 compact 策略是在寫放大,讀放大,空間放大的權衡。

那麼我們 DBA 經常會存在需求儘可能減少空間的使用,因此 DBA 希望能夠隨時觸發手動 compact,而又儘可能的不影響線上的使用。而 RocksDB 預設的手動 compact 策略是最高優先順序的,會阻塞線上的正常流程的合併。

RocksDB 預設的 manual compact 的限制

  1. 當 manual compact 執行時,會等待所有的自動 compact 任務結束,然後才會執行本次 manual compact;

  2. manual 執行期間,自動 compact 無法執行

  • 當 manual 執行很長時間,無法執行自動 compact,導致線上新的寫請求只能在 memtable 中;

  • 當 memtable 個數超過設定的 level0_slowdown_writes_trigger(預設20),寫請求會出被 sleep;

  • 再嚴重一些,當超過 level0_stop_writes_trigger(預設 24),完全停寫;

為了避免這種情況,我們對 compact 的策略進行調整,使得自動 compact 一直優先執行,避免停寫;

總結

恢復時間長

Pika 的儲存引擎是 nemo, nemo 使用的是 RocksDB,我們知道 Rocksdb 啟動不需要載入全部資料,只需要載入幾M的 log 檔案就可以啟動,因此恢復時間非常快;

一主多從,主從切換代價大

在主從切換的時候,新主確定以後,從庫會用當前的偏移量嘗試與新主做一次部分同步,如果部分同步不成功才做全同步,這樣儘可能的減少全同步次數;

緩衝區寫滿問題

Pika 不適用記憶體buffer 進行資料同步,Pika 的主從同步的操作記錄在本地的 binlog 上,binlog 會隨著操作的增長進行 rotate 操作,因此不會出現把緩衝區寫滿的問題;

記憶體昂貴問題

Pika 的儲存引擎 nemo 使用的是 RocksDB,RocksDB 和同時使用記憶體和磁碟減少對記憶體的依賴。同時我們儘可能使用 SSD 盤來存放資料,儘可能跟上 Redis 的效能。

Pika vs Redis

Pika 相對於 Redis,最大的不同就是 Pika 是持久化儲存,資料存在磁碟上,而Redis 是記憶體儲存,由此不同也給 Pika 帶來了相對於 Redis 的優勢和劣勢。

優勢

  • 容量大:Pika 沒有 Redis 的記憶體限制,最大使用空間等於磁碟空間的大小;

  • 載入 db 速度快:Pika 在寫入的時候, 資料是落盤的, 所以即使節點掛了, 不需要 rbd 或者 aof,Pika 重啟不用重新載入資料到記憶體而是直接使用已經持久化在磁碟上的資料, 不需要任何資料回放操作,這大大降低了重啟成本;

  • 備份速度快:Pika備份的速度大致等同於 cp 的速度(拷貝資料檔案後還有一個快照的恢復過程,會花費一些時間),這樣在對於百G大庫的備份是快捷的,更快的備份速度更好的解決了主從的全同步問題。

劣勢

由於 Pika 是基於記憶體和檔案來存放資料,所以效能肯定比 Redis 低一些,但是我們一般使用 SSD 盤來存放資料,儘可能跟上 Redis 的效能。

總結

從以上的對比可以看出,如果你的業務場景的資料比較大,Redis 很難支撐, 比如大於 50G,或者你的資料很重要,不允許斷電丟失,那麼使用 Pika 就可以解決你的問題。

而在實際使用中,大多數場景下 Pika 的效能大約是 Redis 的 50%~80%,在某些特定場景下,例如 range 500,Pika 的效能只有 Redis 的 20%,針對這些場景我們仍然在改進。

在 360 內部使用情況

粗略的統計如下:

當前每天承載的總請求量超過 100 億,例項數超過 100 個

當前承載的資料總量約 3 TB

效能對比

Server Info:

CPU: 24 Cores, Intel® Xeon® 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 大小的資料,寫入 Hash key 50 個,field 1千萬級別。

  • Redis 寫入 5G 大小的資料。

  • Pika:18 個執行緒

  • Redis:單執行緒

首發丨360開源的類Redis儲存系統:Pika

結論

Pika 的單執行緒的效能肯定不如 Redis,Pika 是多執行緒的結構,因此線上程數比較多的情況下,某些資料結構的效能可以優於 Redis。

WiKi

github 地址:

https://github.com/Qihoo360/Pika

github wiki:

https://github.com/Qihoo360/Pika/wiki/Pika介紹

FAQ

1. 如果我們想使用新 DB,那核心問題是如何進行資料遷移,從 Redis 遷移到 Pika 需要經過幾個步驟?

開發需要做的:

開發不需要做任何事,不用改程式碼、不用替換 driver(Pika 使用原生 Redis 的 driver),什麼都不用動,看 DBA 幹活就好。

DBA 需要做的

  1. 遷移 Redis 資料到 Pika;

  2. 將 Redis 的資料實時同步到 Pika,確保 Redis 與 Pika 的資料始終一致;

  3. 切換 LVS 後端 IP,由 Pika 替換 Redis

2. 遷移過程中需要停業務/業務會受到影響嗎?

然而並不會

3. 遷移是無縫且溫和的嗎?

那當然

4. 和你們公司內部的 bada 有什麼區別?

我們之前在 bada 上面支援過 Redis 的多資料結構,並且相容 Redis 協議,但是遇到了問題。

在分散式系統裡面,對 key 的 hash 場景的通常是兩種方案:

  • 以 BigTable 為代表的,支援 range key 的 hash 方案。這個方案的好處是可以實現動態的擴充套件。

  • 以 Dynamo 為代表取模的 hash 方案,這個方案的好處是時間簡單。

我們 bada 目前支援的是取模的 hash 方案,在實現 Redis 的多資料結構的時候,比如 hash 我們採用 key 取模找到對應的分片。那麼這樣帶來的問題是由於多資料結構裡面 key 不多,field 比較多的場景還是大部分的情況,因此極容易照成分片的不均勻,效能退化很明顯。

5. 為什麼 Pika 使用多執行緒而不是像 Redis 單執行緒的結構

因為 Redis 所有的操作都是對於記憶體的操作,因此理論上 Redis 的每次操作很短的。

Q&A

1、資料分片是在代理層做的?集合操作落在不同的槽,比如 mget,是在代理層聚合的?

陳宗志:目前沒有對資料進行分片,你可以理解成和單機 Redis 類似,支援 master-slave 的架構,因此單個 pika 例項儲存的大小的限制是磁碟大小的限制。

2、pika 支援的客戶端有哪些,是否支援 pipelining?

陳宗志:pika 支援所有的 Redis 客戶端,因為 pika 設計之初就考慮到了使用者的遷移成本,因此各種語言的客戶端都支援。pipelining 是客戶端來做的,因此我們是支援 pipelining 的。

3、為什麼不考慮 Redis cluster shard 呢?

陳宗志:我們開始做 pika 的時候,Redis cluster shard 還不完善,而且 Redis cluster 定位的場景和 pika 還是有區別。目前我們內部還沒大範圍使用 Redis cluster。

4、不理解前面為什麼加 LVS?Redis 類服務都是帶狀態,負載反而用吧?

陳宗志:我們暴露給使用者的 ip 是我們 LVS 的 ip。在 Redis 前面 LVS 是為了方便主從切換,這樣可以做到使用者完全不感知。這裡 LVS 下面掛的多個 Redis 例項,都是 master-slave 結構的。

5、有沒有對比過 ssdb,LevelDB?優勢是什麼?

陳宗志:我們公司內部有業務部門用 ssdb,目前除了遊戲大部分的 ssdb 已經遷移到 pika上來。我覺得 pika 的優勢在於我們程式碼實現的比較細,效能會比較好。

6、儲存引擎為什麼沒有選擇 LevelDB 呢,另外市面上有類似的方案如 ssdb,有什麼不同之處嗎?

陳宗志:儲存引擎上我們在 LevelDB,RocksDB 上面做過對比。LevelDB,RocksDB 在資料量比較小的時候效能差異不大,但是在資料量比較大的情況下,比如 200G 的時候,RocksDB 的效能會比 LevelDB 要來得好。

但是 RocksDB 也有他的缺點,就是程式碼沒有 LevelDB 來的那麼優雅,我一直覺得一個好的 c++ 程式設計師看 LevelDB 程式碼和 effective c++ 就好了

7、若類似於單機 Redis,那麼單機效能是個瓶頸吧?大量的客戶端連線,命令處理,以及網路卡流量等

陳宗志:是的。所以目前內部的 pika 的架構是支援一主多從、多機房自洽的方案。目前線上最多一個主 14 個從這樣的結構。DBA 可以很容易的slaveof 給一個主掛上slave,然後進行資料的全同步過程。

8、pika 的多執行緒比 Redis 的全記憶體,在 get上竟然快兩倍?set 也快,不存在多執行緒的鎖消耗嗎?

陳宗志:這裡大家可以看到,這個測試結果是 pika work thread 開了 18 個。

在多資料結構的介面裡面 kv 的結構的效能是最好的,而多資料結構的介面比如 hash、zset 等等就算開了 18 個執行緒,效能依然不如 Redis 要來得好。因為 hash、zset 等資料結構需要有搶佔多資料結構後設資料鎖的開銷,因此效能很容易下來。但是 kv 介面基本沒有鎖的開銷。唯一的鎖開銷就是 RocksDB 為了實現執行緒安全增加的鎖,因此這個結果也是可以理解了。

9、完全是因為分散式切片不均的緣故,而放棄分散式叢集嗎?m-s架構每個節點不都是全量資料,佔用更多資源嗎?

陳宗志:其實我們在 bada 裡面增加了多資料結構的介面,並且相容了 Redis 的協議,但是後來使用者的使用中,發現其實使用多資料結構介面的使用者資料量其實不是特別大。單機 1T 的盤基本都能夠承受下來。但是還是因為 Hash 分散式切片不均衡,導致我們的維護成本增加,因此我們去實現了 m-s 架構方案。

目前 bada 的方案也是和 pika 並存的方案,我們會根據使用者具體的使用場景推薦使用的儲存方案。我一直覺得肯定不是一套儲存方案解決公司內部的所有需求,一定是某一個方案更適用於某一種儲存方案。

10、除了類比為單機 Redis 外,有沒有考慮分散式支援?比如 Redis 的 sentinel 或者支援 Codis 這樣可能其它 Redis 叢集可以無縫遷移。

陳宗志:Pika 目前並沒有使用類似 Redis 的 sentinel,pika 前面是掛 LVS 來負責主從切換。目前也沒有使用 Codis 這樣的 proxy 方案。

11、一主 14 個從?主從同步豈不是很慢?另外,從是隻讀的吧,讀從的話,從的資料可能是過期的,資料一致性怎麼解決?

陳宗志:一主 14 從的場景是使用者的寫入都是晚上定期的灌資料,讀取的話從各個從庫進行讀取。因此這個資料一致性是使用者可以接受的場景。

http://toutiao.com/a6283628736621461761/

相關文章