為滿足運(yùn)維人員對(duì)于pika可以更好地運(yùn)維,需要方便地將數(shù)據(jù)從pika遷移到redis,在pika系統(tǒng)中之前已經(jīng)為運(yùn)維人員提供了Redis請(qǐng)求實(shí)時(shí)copy到pika工具可以實(shí)時(shí)將redis上的請(qǐng)求同步發(fā)送到pika,這個(gè)工具則是為了能夠?qū)㈦x線的pika數(shù)據(jù)遷移至redis。
使用串行方式,將整個(gè)遷移過(guò)程分為三個(gè)階段,如下:
驗(yàn)證方案可行,但是速度難以接受,遷移10G數(shù)據(jù)需要20小時(shí)以上。從遷移過(guò)程的三個(gè)步驟中,可以看到無(wú)論是數(shù)據(jù)掃描還是,指令的發(fā)送和接收響應(yīng)都非常慢。分析其原因,主要在于:
在版本1不能滿足速度要求之后,發(fā)現(xiàn)redis官方客戶端提供有一種可以大規(guī)模數(shù)據(jù)插入的方式pipeline mode,使用的基本形式如下:
cat cmd.txt | redis-cli --pipe
# 其中cmd.txt中存的是符合redis協(xié)議的指令
對(duì)現(xiàn)有程序稍加改動(dòng),將生成的redis指令直接寫(xiě)入標(biāo)準(zhǔn)輸入流,即可使用pipe mode方式,通過(guò)千萬(wàn)條數(shù)據(jù)測(cè)試,在本地效果提高30%以上。這種方案速度較之前大幅提升,在于節(jié)省了大量浪費(fèi)在每個(gè)指令返回的時(shí)間。
但是直接使用這種方案,雖然速度提升不少,完成時(shí)間還是不能滿足要求。由于這種方式,還是只能使用一個(gè)發(fā)送端,不方便后期進(jìn)行多線程的優(yōu)化。接下來(lái)需要自己定制實(shí)現(xiàn)pipeline mode
在pika自己實(shí)現(xiàn)的客戶端中,只能是逐條發(fā)送指令,逐條接收。redis官方客戶端的實(shí)現(xiàn)方式:
實(shí)質(zhì)上官方客戶端是將生成指令和發(fā)送指令分別放在兩個(gè)不同的進(jìn)程中,在這里模擬標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出,則可以自己開(kāi)一條管道,一端將指令寫(xiě)入,一端讀出指令并發(fā)送。
在實(shí)現(xiàn)了之后,速度確實(shí)有提升,但是發(fā)現(xiàn)之前官方客戶端從標(biāo)準(zhǔn)輸入中讀入數(shù)據(jù)是因?yàn)槭褂脠?chǎng)景所限制,大可將管道那一層去掉,讓自己管理buf,就少了將數(shù)據(jù)寫(xiě)入內(nèi)核,有從內(nèi)核讀出過(guò)程,只是自己需要維護(hù)buf的讀寫(xiě),這是一個(gè)典型的生產(chǎn)者消費(fèi)者模型。在分析完成之后,對(duì)pipeline進(jìn)行小幅的改進(jìn)。
在完成了上面的版本之后,就可以對(duì)整個(gè)流程進(jìn)行多線程的優(yōu)化。由于當(dāng)前數(shù)據(jù)的發(fā)送并非是整條發(fā)送出去,buf的管理都粒度都是在字符級(jí)別,所以采用一個(gè)指令生成線程(parser)和發(fā)送線程(sender)一一對(duì)應(yīng)。
整體架構(gòu)圖如下:
至此,數(shù)據(jù)遷移工具在性能上已經(jīng)從原先需要20小時(shí)遷移的數(shù)據(jù)到現(xiàn)在大概40分鐘左右,完全滿足最初的時(shí)間要求。
名稱 | 內(nèi)存 | cpu |
---|---|---|
bada05 | 160G | 24*2.6Hz |
bada06 | 160G | 24*2.6Hz |
名稱 | key長(zhǎng)度 | 億條數(shù)據(jù)磁盤(pán)占用 | 1G數(shù)據(jù)數(shù)據(jù)條數(shù) |
---|---|---|---|
長(zhǎng)數(shù)據(jù) | 30字符 | 2.1G | 0.46億條 |
短數(shù)據(jù) | 180字符 | 6.3G | 0.15億條 |
bada05->bada06 短數(shù)
數(shù)據(jù)庫(kù) | 客戶端數(shù)量 | 數(shù)據(jù)量 | 數(shù)據(jù)條數(shù) | 消耗時(shí)間 | 速度(每小時(shí)) |
---|---|---|---|---|---|
All | 10 | 15.6G | 1.5億*5 | 3.5小時(shí) | 4.5G/2.2億 |
kv | 10 | 1.2G | 1.5億 | 32min | 2.3G/2.8億 |
hash | 10 | 3.2G | 1.5億 | 45min | 4.3G/2億 |
set | 10 | 2.8G | 1.5億 | 40min | 4.2G/2.3億 |
zset | 10 | 5.6G | 1.5億 | 41min | 8.2G/2.2億 |
遠(yuǎn)程測(cè)試:bada05->bada06
數(shù)據(jù)庫(kù)| 發(fā)送端數(shù)量| 數(shù)據(jù)量| 數(shù)據(jù)條數(shù) |消耗時(shí)間| 速度(每小時(shí)) ---|---|---|---|---|---|---|---|---|---|---|--- All(短)| 10| 16G| 1.5億*5 |3.5h| 4.5G/2.1億 set(短)| 10| 2.8G| 1.5億 |40min| 4.2G/2.3億 set(長(zhǎng))| 10| 2.5G |3.8千萬(wàn) |10min |15G/2.2億 hash(長(zhǎng))| 10| 3.3G|3.8千萬(wàn) |10min |20G/2.2億 kv(長(zhǎng))| 10| 1.6G| 3.8千萬(wàn)| 8min| 12G/2.8億 list(長(zhǎng))| 10| 2.8|3.8千萬(wàn)| 10min| 16G/2.2億 注:由于長(zhǎng)數(shù)據(jù)中,不同數(shù)據(jù)類型key有重復(fù),無(wú)法正常導(dǎo)入redis,故采用分庫(kù)導(dǎo)入
bada05->bada06 短數(shù)據(jù)
線程數(shù)量| 數(shù)據(jù)量|數(shù)據(jù)條數(shù) |消耗時(shí)間| 速度(每小時(shí)) ---|---|---|---|---|---|---|---|--- 10| 16G| 1.5億5| 3.5小時(shí)| 4.5G/2.1億 16| 16G| 1.5億5| 2.3小時(shí)| 7.1G/3.3億 20| 16G| 1.5億*5| 2.1小時(shí)| 7.5G/3.5億
|線程數(shù)量| 數(shù)據(jù)量| 數(shù)據(jù)條數(shù)| 速度(每小時(shí)) ---|---|---|---|---|---|--- 異地|10 |16G |1.5億5| 3.5h 4.5G/2.1億 本地|10 |16G |1.5億5| 1.9h 8.1G/3.8億
更多建議: