pika常見問題解答(FAQ)

2018-09-28 10:41 更新

1 編譯安裝

Q1: 支持的系統(tǒng)?

A1: 目前只支持Linux環(huán)境,包括Centos,Ubuntu; 不支持Windowns, Mac

Q2: 怎么編譯安裝?

A2: 參考編譯安裝wiki

Q3: Ubuntu編譯偶爾報(bào)錯(cuò)isnan isinf was not declared?

A3: 一些舊版本的pika對Ubuntu環(huán)境兼容不好,某些情況下會(huì)出現(xiàn);可以先修改代碼,用std::isnan和std::isinf替代isnan,isinf, 并包含頭文件cmath。 我們會(huì)在新版兼容這個(gè)。

#include <cmath>

2 設(shè)計(jì)與實(shí)現(xiàn)

Q1: 為什么要開那么多線程?比如purge,搞個(gè)定時(shí)任務(wù)不就好了。難道編程框架不支持定時(shí)器?

A1: pika有一些比較耗時(shí)的任務(wù),如刪binlog,掃描key,備份,同步數(shù)據(jù)文件等等,為了不影響正常的用戶請求,這些任務(wù)都是放到后臺(tái)執(zhí)行的,并且將能并行的都放到不同線程里來最大程度上提升后臺(tái)任務(wù)的執(zhí)行速度;你說的變成框架是pink嗎?pink是支持定時(shí)器的,每一個(gè)workerthread只要用戶定義了cronhandle和頻率,就會(huì)定時(shí)執(zhí)行要執(zhí)行的內(nèi)容,不過這時(shí)候worker是被獨(dú)占的,響應(yīng)不了用戶請求,所以占時(shí)的任務(wù)最好還是單獨(dú)開線程去做,redis的bio也是這個(gè)原因

Q2: heartbeat讓sender做不就好了?或者說sender有必要那么多線程嗎?

A2: 這主要有兩個(gè)原因,第一為了提高同步速度,sender只發(fā)不收,receiver只收不發(fā),心跳是又單獨(dú)的線程去做,如果心跳又sender來做,那么為了一秒僅有一次的心跳還要去復(fù)雜化sender和receiver的邏輯;第二其實(shí)前期嘗試過合并在一起來進(jìn)行連接級(jí)別的存活檢測,當(dāng)寫入壓力過大的時(shí)候會(huì)心跳包的收發(fā)會(huì)延后,導(dǎo)致存活檢測被影響,slave誤判master超時(shí)而進(jìn)行不必要的重連

Q3: nemo存儲(chǔ)hash的實(shí)際key,第一個(gè)字節(jié)是?header?一個(gè)類型標(biāo)記?是說他是個(gè)hash類型?

A3: 的確是一個(gè)header,不過不是為了標(biāo)記它是hash,因?yàn)閚emo底下已經(jīng)將string,hash,list,zset,set這五個(gè)數(shù)據(jù)結(jié)構(gòu)分成的5個(gè)庫,互不影響,之所以有header是因?yàn)橐粋€(gè)hash有一個(gè)meta key和一堆field key,meta key對應(yīng)的value記錄的是這個(gè)hash的基礎(chǔ)信息,如hash的size等等,這個(gè)header也是區(qū)分meta key和field key用的

Q4: list數(shù)據(jù)結(jié)構(gòu)里面的curr_seq是個(gè)什么東西?

A4: list的實(shí)現(xiàn)是完全基于kv實(shí)現(xiàn)的list,通過seq來實(shí)現(xiàn)list類似prev和next指針,cur_seq是在meta信息里的,也就是當(dāng)前已經(jīng)用到那個(gè)seq了,新來的節(jié)點(diǎn)從這個(gè)seq開始遞增接著用

Q5: binlog里面存儲(chǔ)的是轉(zhuǎn)化后的put,delete?還是存儲(chǔ)的原生redis命令?

A5: 存的是redis的命令

Q6: rsync的deamon模式,這個(gè)rsync是linux上的rsync命令?

A6: 是的,pika前期為了更快的實(shí)現(xiàn)全同步的功能,此處是直接調(diào)用rsync命令來完成數(shù)據(jù)文件的收發(fā),也是由它來進(jìn)行文件的續(xù)傳校驗(yàn)等

Q7: dump db文件是rocksdb本身就帶的功能?具體怎么搞的?

A7: rocksdb提夠?qū)Ξ?dāng)前db快照備份的功能,我們基于此,在dump時(shí)先對pika阻住用戶的寫,然后記錄當(dāng)前的binlog偏移量并且調(diào)用rocksdb的接口來拿到當(dāng)前db的元信息,這個(gè)時(shí)候就可以放開用戶寫,然后基于這個(gè)元信息來進(jìn)行快照數(shù)據(jù)的后臺(tái)拷貝,阻寫的時(shí)間很短

Q8: 先寫binlog再執(zhí)行,如果這時(shí)候掛了,命令還沒執(zhí)行,但是寫入到binlog里面了怎么辦?

A8: master是先寫db再寫binlog,之前slave只用一個(gè)worker來同步會(huì)在master寫入壓力很大的情況下由于slave一個(gè)worker寫入太慢而造成同步差距過大,后來我們調(diào)整結(jié)構(gòu),讓slave通過多個(gè)worker來寫提高寫入速度,不過這時(shí)候有一個(gè)問題,為了保證主從binlog順序一致,寫binlog的操作還是只能又一個(gè)線程來做,也就是receiver,所以slave這邊是先寫binlog在寫db,所以slave存在寫完binlog掛掉導(dǎo)致丟失數(shù)據(jù)的問題,不過redis在master寫完db后掛掉同樣會(huì)丟失數(shù)據(jù),所以redis采用全同步的辦法來解決這一問題,pika同樣,默認(rèn)使用部分同步來繼續(xù),如果業(yè)務(wù)對數(shù)據(jù)十分敏感,此處可以強(qiáng)制slave重啟后進(jìn)行全同步即可

Q9: BinlogBGWorker線程之間還是要按照binlog順序執(zhí)行,這塊并發(fā)能提高多少性能?

A9: 之前主從同步的差異是由主的多個(gè)worker寫入而從只有一個(gè)worker寫入帶來的,現(xiàn)在的做法提高了從寫db的速度,不過協(xié)議解析還是有一個(gè)線程來做,還是有瓶頸,不過這樣的優(yōu)化主從同步的性能提高了3~5倍左右,如果key很少的話,優(yōu)化不明顯,因?yàn)閟lave這面是通過key的hash值來sharding到其中一個(gè)worker上的

Q10: 秒刪,每次put都要去查詢key的最新版本?也就是說每次寫避免伴隨一次讀?

A10: pika多數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)主要是“meta key + 普通key”來實(shí)現(xiàn)的,所以對于多數(shù)據(jù)結(jié)構(gòu)的讀寫,肯定都是對rocksdb進(jìn)行2次及以上的讀寫次數(shù),你說的版本信息我們是存在meta_key中的,和其他meta信息一起被讀出來,其實(shí)并沒有因?yàn)榘姹咎?hào)而額外增加讀寫次數(shù)

Q11: 為什么 Pika 使用多線程而不是像 Redis 單線程的結(jié)構(gòu)?

A11: 因?yàn)?Redis 所有的操作都是對于內(nèi)存的操作,因此理論上 Redis 的每次操作很短的。

Q12: 數(shù)據(jù)分片是在代理層做的?集合操作落在不同的槽,比如 mget,是在代理層聚合的?

A12: 目前沒有對數(shù)據(jù)進(jìn)行分片,你可以理解成和單機(jī) Redis 類似,支持 master-slave 的架構(gòu),因此單個(gè) pika 實(shí)例存儲(chǔ)的大小的限制是磁盤大小的限制。

Q13: pika 支持的客戶端有哪些,是否支持 pipelining?

A13: pika 支持所有的 Redis 客戶端,因?yàn)?pika 設(shè)計(jì)之初就考慮到了用戶的遷移成本,因此各種語言的客戶端都支持。pipelining 是客戶端來做的,因此我們是支持 pipelining 的。

Q14: 為什么不考慮 Redis cluster shard 呢?

A14: 我們開始做 pika 的時(shí)候,Redis cluster shard 還不完善,而且 Redis cluster 定位的場景和 pika 還是有區(qū)別。目前我們內(nèi)部還沒大范圍使用 Redis cluster。

Q15: 不理解前面為什么加 LVS?Redis 類服務(wù)都是帶狀態(tài),負(fù)載反而用吧?

A15: 我們暴露給用戶的 ip 是我們 LVS 的 ip。在 Redis 前面 LVS 是為了方便主從切換,這樣可以做到用戶完全不感知。這里 LVS 下面掛的多個(gè) Redis 實(shí)例,都是 master-slave 結(jié)構(gòu)的。

Q16: 有沒有對比過 ssdb,LevelDB?優(yōu)勢是什么?

A16: 我們公司內(nèi)部有業(yè)務(wù)部門用 ssdb,目前除了游戲大部分的 ssdb 已經(jīng)遷移到 pika上來。我覺得 pika 的優(yōu)勢在于我們代碼實(shí)現(xiàn)的比較細(xì),性能會(huì)比較好。

Q17: 存儲(chǔ)引擎為什么沒有選擇 LevelDB 呢,另外市面上有類似的方案如 ssdb,有什么不同之處嗎?

A17: 存儲(chǔ)引擎上我們在 LevelDB,RocksDB 上面做過對比。LevelDB,RocksDB 在數(shù)據(jù)量比較小的時(shí)候性能差異不大,但是在數(shù)據(jù)量比較大的情況下,比如 200G 的時(shí)候,RocksDB 的性能會(huì)比 LevelDB 要來得好。但是 RocksDB 也有他的缺點(diǎn),就是代碼沒有 LevelDB 來的那么優(yōu)雅,我一直覺得一個(gè)好的 c++ 程序員看 LevelDB 代碼和 effective c++ 就好了。

Q18: 若類似于單機(jī) Redis,那么單機(jī)性能是個(gè)瓶頸吧?大量的客戶端連接,命令處理,以及網(wǎng)卡流量等

A18: 是的。所以目前內(nèi)部的 pika 的架構(gòu)是支持一主多從、多機(jī)房自洽的方案。目前線上最多一個(gè)主 14 個(gè)從這樣的結(jié)構(gòu)。DBA 可以很容易的slaveof 給一個(gè)主掛上slave,然后進(jìn)行數(shù)據(jù)的全同步過程。

Q19: pika 的多線程比 Redis 的全內(nèi)存,在 get上竟然快兩倍?set 也快,不存在多線程的鎖消耗嗎?

A19: 這里大家可以看到,這個(gè)測試結(jié)果是 pika work thread 開了 18 個(gè)。

在多數(shù)據(jù)結(jié)構(gòu)的接口里面 kv 的結(jié)構(gòu)的性能是最好的,而多數(shù)據(jù)結(jié)構(gòu)的接口比如 hash、zset 等等就算開了 18 個(gè)線程,性能依然不如 Redis 要來得好。因?yàn)?hash、zset 等數(shù)據(jù)結(jié)構(gòu)需要有搶占多數(shù)據(jù)結(jié)構(gòu)元數(shù)據(jù)鎖的開銷,因此性能很容易下來。但是 kv 接口基本沒有鎖的開銷。唯一的鎖開銷就是 RocksDB 為了實(shí)現(xiàn)線程安全增加的鎖,因此這個(gè)結(jié)果也是可以理解了。

Q20: 完全是因?yàn)榉植际角衅痪木壒?,而放棄分布式集群嗎?m-s架構(gòu)每個(gè)節(jié)點(diǎn)不都是全量數(shù)據(jù),占用更多資源嗎?

A20: 其實(shí)我們在 bada 里面增加了多數(shù)據(jù)結(jié)構(gòu)的接口,并且兼容了 Redis 的協(xié)議,但是后來用戶的使用中,發(fā)現(xiàn)其實(shí)使用多數(shù)據(jù)結(jié)構(gòu)接口的用戶數(shù)據(jù)量其實(shí)不是特別大。單機(jī) 1T 的盤基本都能夠承受下來。但是還是因?yàn)?Hash 分布式切片不均衡,導(dǎo)致我們的維護(hù)成本增加,因此我們?nèi)?shí)現(xiàn)了 m-s 架構(gòu)方案。

目前 bada 的方案也是和 pika 并存的方案,我們會(huì)根據(jù)用戶具體的使用場景推薦使用的存儲(chǔ)方案。我一直覺得肯定不是一套存儲(chǔ)方案解決公司內(nèi)部的所有需求,一定是某一個(gè)方案更適用于某一種存儲(chǔ)方案。

Q21: 除了類比為單機(jī) Redis 外,有沒有考慮分布式支持?比如 Redis 的 sentinel 或者支持 Codis 這樣可能其它 Redis 集群可以無縫遷移。

A21: Pika 目前并沒有使用類似 Redis 的 sentinel,pika 前面是掛 LVS 來負(fù)責(zé)主從切換。目前也沒有使用 Codis 這樣的 proxy 方案。

Q22: 一主 14 個(gè)從?主從同步豈不是很慢?另外,從是只讀的吧,讀從的話,從的數(shù)據(jù)可能是過期的,數(shù)據(jù)一致性怎么解決?

A22: 一主 14 從的場景是用戶的寫入都是晚上定期的灌數(shù)據(jù),讀取的話從各個(gè)從庫進(jìn)行讀取。因此這個(gè)數(shù)據(jù)一致性是用戶可以接受的場景。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)