一、常見redis數(shù)據(jù)遷移方式
業(yè)內,常見的redis數(shù)據(jù)遷移方式有以下三種:aof(日志文件)、rdb(快照文件)、replication(主從復制)。
其中,aof和rdb兩種方式適用于跨網(wǎng)絡(網(wǎng)絡隔離)的redis實例之間的數(shù)據(jù)遷移,在源實例上通過指令(bgrewriteaof/bgsave)生成aof或者rdb文件 -> 下載數(shù)據(jù)文件 -> 上傳數(shù)據(jù)文件 -> 啟動目標實例,完成數(shù)據(jù)遷移。aof和rdb的差異,主要體現(xiàn)在數(shù)據(jù)格式和數(shù)據(jù)加載速度兩個方面,前者是純文本格式(redis文本協(xié)議的流水記錄),加載的過程相當于歷史重放,而后者是二進制格式,直接進行加載,所以一般情況下rdb數(shù)據(jù)加載會比aof加載快!這也是網(wǎng)上建議使用rdb做跨網(wǎng)絡數(shù)據(jù)遷移的一個重要的原因。
- aof
- rdb
而replication方式,適用于同一網(wǎng)絡內的redis實例之間的數(shù)據(jù)遷移,在目標實例上通過指令(slaveof)完成數(shù)據(jù)全量復制遷移,在單實例的擴容應用上最適合。
- replication
二、開發(fā)redis-migration的需求
以上三種數(shù)據(jù)遷移方式都 只解決點對點的數(shù)據(jù)遷移 (缺陷1),而且aof和rdb還存在 增量數(shù)據(jù)不能同步 (缺陷2)的問題。
事實上,我們開發(fā)redis-migration這個工具的原始需求來自于網(wǎng)易私有云 redis集群的橫向擴容:
- redis集群橫向擴容
三、如何開發(fā)redis-migration?
工具 定義
比較 前面三種數(shù)據(jù)遷移方式,思考能不能把replication(主從復制)的過程剝離出來做成一個獨立工具呢? 在連接源redis實例時候把自己模擬成slave,在連接目標redis實例(集群)時候把自己模擬成客戶端,如下:
這樣的話,源redis實例即使是分布式集群(多個源redis實例),也只需要同時啟動多個遷移工具實例就能解決了,如下:
調研過程
定下開發(fā)遷移工具后,調研了如下的對象:
- redis-benchmark多客戶端并發(fā);
- redis replication交互過程;
- hiredis框架,報文組裝和解析;
- RDB文件解析;
- AOF文件解析;
流程設計
下圖是遷移工具的時序圖,分為三部分:快照數(shù)據(jù)和增量數(shù)據(jù),其中增量數(shù)據(jù)分為2個階段,第1階段會落地成文件,第二階段不落地直接TCP轉發(fā)。
編碼實現(xiàn)
省略1萬字,二進制文件: redis-migration ,源碼后續(xù)放出。
技術難點
- 解析數(shù)據(jù)文件:包括AOF和RDB,相對而言解析AOF文件會簡單些,它是文本格式的,按照redis協(xié)議純文本處理即可;而RDB文件是二進制格式的,自己重新實現(xiàn)沒這個必要,因為redis已經有解析RDB的接口,但源碼是和redis本身是耦合在一起的,比如對各種共享對象、全局變量、數(shù)據(jù)結構dict/sds等的依賴,所以最后實現(xiàn)上變成了redis-benchmark.c和redis.c的結合體;
- 處理redis協(xié)議:解析來自數(shù)據(jù)源的redis數(shù)據(jù),讀取落地的RDB和AOF文件數(shù)據(jù)組裝成redis協(xié)議數(shù)據(jù)。雖然客戶端使用的還是hiredis庫,但是請求和應答報文,都不能使用庫提供的接口來組裝和解析,需要重新實現(xiàn),這一塊工作量比較大。RDB和AOF的請求報文組裝以及各自應答消息的解析與校驗,其中RDB數(shù)據(jù)是二進制的,所以需要逐字段進行組裝,hiredis庫沒有提供這樣的接口,而且假設提供了也需要評估起性能;同時RDB數(shù)據(jù)里會設置key的有效時間,一條RDB數(shù)據(jù)可能需要組裝成兩條redis指令;兩種數(shù)據(jù)都解析出類型后,用來精確判斷應答消息的正確與否;
- 設計高效遷移:RDB數(shù)據(jù)有個特點,它保存的是每個key的快照,無時序要求,所以可以考慮并發(fā)發(fā)送的方式,提高遷移速度;而AOF數(shù)據(jù),有時序要求,在目的地進行重放加載,不能并發(fā),否則會亂序,出現(xiàn)數(shù)據(jù)錯誤,只能一個客戶端發(fā)送,這時采用的是pipeline(批量)的方式;
- 方便調試定位:遷移工具和數(shù)據(jù)源、數(shù)據(jù)目的地的交互都是在線TCP流,而且都是瞬間完成的,對于中間的錯誤和異常,比較難以捕捉,現(xiàn)在的做法是在數(shù)據(jù)流入和流出的地方統(tǒng)一加了十六進制的報文日志;
功能特點
- 輕量級 :僅增加了1個redis-migration.c文件,同時在Makefile文件中增加編譯redis-migration二進制程序的2行指令;單線程,異步消息驅動模型,輕量化,工具編譯出來約4M大小;
- 高性能 :前面有人可能會好奇,單線程程序怎么實現(xiàn)多客戶端并發(fā)?是這樣的,因為一個客戶端的請求是串行的,存在RTT這樣一個時間窗口,那么在這個時間窗口里并發(fā)多個客戶端就可以避免系統(tǒng)等待,極大提高性能;另外,AOF遷移時候使用了pipeline特性,批量發(fā)送,減少RTT來加速遷移;
- 低成本 :遷移過程中的 數(shù)據(jù)都做了落地處理 ,工具本身沒有對數(shù)據(jù)進行加載,內存開銷就很小,這一點非常重要!
- 易操作:啟動后,觀察遷移進度日志即可;
redis-migration遷移工具不僅可以解決外部實例遷往網(wǎng)易私有云redis集群、私有云redis集群橫向擴容的問題,也可以解決外部redis集群的擴容問題, 具有通用價值 。比如:一個客戶端分片的分布式redis集群,通過redis-migration工具(外加一個數(shù)據(jù)分片代理程序,比如twemproxy)將數(shù)據(jù)實時同步到新的集群,然后應用直接切到新集群上,集群橫向擴容完成,中間不丟失任何數(shù)據(jù)!
應用案例
網(wǎng)易私有云線上已經有多個應用使用redis-migration進行了數(shù)據(jù)遷移,包括外部實例遷移、私有云分布式redis集群擴容等,下圖為幾個典型的應用:
另外,網(wǎng)易新聞客戶端推薦系統(tǒng)約2T規(guī)模的redis數(shù)據(jù),也將依賴redis-migration遷移到私有云redis集群上來,目前正處于資源準備階段。
四、競爭對手
豌豆夾redis數(shù)據(jù)遷移工具
使用go語言實現(xiàn),數(shù)據(jù)在線轉發(fā),沒有落地,比較吃內存,經過簡單測試發(fā)現(xiàn)遷移效率沒有redis-migration高,源碼見 : https://github.com/CodisLabs/redis-port
騰訊云redis數(shù)據(jù)遷移工具
騰訊云redis數(shù)據(jù)遷移工具crs-port,居然是豌豆夾的二進制程序改了個名-_-##,下載地址:http://www.qcloud.com/wiki/%E4%BA%91%E5%AD%98%E5%82%A8Redis(CRS)%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%85%A5
分布式系統(tǒng)的橫向擴容歷來是很難實現(xiàn)的,對redis集群這種純內存數(shù)據(jù)庫也不例外,而redis-migration遷移工具是對分布式redis集群橫向擴容實現(xiàn)的一次實踐,事實證明效果比較理想!
歡迎補充和測試。