http://www.open-open.com/lib/view/open1457000015046.html
一、常見redis數據遷移方式
業內,常見的redis數據遷移方式有以下三種:aof(日志文件)、rdb(快照文件)、replication(主從復制)。
其中,aof和rdb兩種方式適用于跨網絡(網絡隔離)的redis實例之間的數據遷移,在源實例上通過指令(bgrewriteaof/bgsave)生成aof或者rdb文件 -> 下載數據文件 -> 上傳數據文件 -> 啟動目標實例,完成數據遷移。aof和rdb的差異,主要體現在數據格式和數據加載速度兩個方面,前者是純文本格式(redis文本協議的流水記錄),加載的過程相當于歷史重放,而后者是二進制格式,直接進行加載,所以一般情況下rdb數據加載會比aof加載快!這也是網上建議使用rdb做跨網絡數據遷移的一個重要的原因。


而replication方式,適用于同一網絡內的redis實例之間的數據遷移,在目標實例上通過指令(slaveof)完成數據全量復制遷移,在單實例的擴容應用上最適合。

二、開發redis-migration的需求
以上三種數據遷移方式都 只解決點對點的數據遷移 (缺陷1),而且aof和rdb還存在 增量數據不能同步 (缺陷2)的問題。
事實上,我們開發redis-migration這個工具的原始需求來自于網易私有云 redis集群的橫向擴容:

三、如何開發redis-migration?
工具 定義
比較 前面三種數據遷移方式,思考能不能把replication(主從復制)的過程剝離出來做成一個獨立工具呢? 在連接源redis實例時候把自己模擬成slave,在連接目標redis實例(集群)時候把自己模擬成客戶端,如下:

這樣的話,源redis實例即使是分布式集群(多個源redis實例),也只需要同時啟動多個遷移工具實例就能解決了,如下:

調研過程
定下開發遷移工具后,調研了如下的對象:
- redis-benchmark多客戶端并發;
- redis replication交互過程;
- hiredis框架,報文組裝和解析;
- RDB文件解析;
- AOF文件解析;
流程設計
下圖是遷移工具的時序圖,分為三部分:快照數據和增量數據,其中增量數據分為2個階段,第1階段會落地成文件,第二階段不落地直接TCP轉發。

編碼實現
省略1萬字,二進制文件: redis-migration ,源碼后續放出。
技術難點
- 解析數據文件:包括AOF和RDB,相對而言解析AOF文件會簡單些,它是文本格式的,按照redis協議純文本處理即可;而RDB文件是二進制格式的,自己重新實現沒這個必要,因為redis已經有解析RDB的接口,但源碼是和redis本身是耦合在一起的,比如對各種共享對象、全局變量、數據結構dict/sds等的依賴,所以最后實現上變成了redis-benchmark.c和redis.c的結合體;
- 處理redis協議:解析來自數據源的redis數據,讀取落地的RDB和AOF文件數據組裝成redis協議數據。雖然客戶端使用的還是hiredis庫,但是請求和應答報文,都不能使用庫提供的接口來組裝和解析,需要重新實現,這一塊工作量比較大。RDB和AOF的請求報文組裝以及各自應答消息的解析與校驗,其中RDB數據是二進制的,所以需要逐字段進行組裝,hiredis庫沒有提供這樣的接口,而且假設提供了也需要評估起性能;同時RDB數據里會設置key的有效時間,一條RDB數據可能需要組裝成兩條redis指令;兩種數據都解析出類型后,用來精確判斷應答消息的正確與否;
- 設計高效遷移:RDB數據有個特點,它保存的是每個key的快照,無時序要求,所以可以考慮并發發送的方式,提高遷移速度;而AOF數據,有時序要求,在目的地進行重放加載,不能并發,否則會亂序,出現數據錯誤,只能一個客戶端發送,這時采用的是pipeline(批量)的方式;
- 方便調試定位:遷移工具和數據源、數據目的地的交互都是在線TCP流,而且都是瞬間完成的,對于中間的錯誤和異常,比較難以捕捉,現在的做法是在數據流入和流出的地方統一加了十六進制的報文日志;
功能特點
- 輕量級 :僅增加了1個redis-migration.c文件,同時在Makefile文件中增加編譯redis-migration二進制程序的2行指令;單線程,異步消息驅動模型,輕量化,工具編譯出來約4M大小;
- 高性能 :前面有人可能會好奇,單線程程序怎么實現多客戶端并發?是這樣的,因為一個客戶端的請求是串行的,存在RTT這樣一個時間窗口,那么在這個時間窗口里并發多個客戶端就可以避免系統等待,極大提高性能;另外,AOF遷移時候使用了pipeline特性,批量發送,減少RTT來加速遷移;
- 低成本 :遷移過程中的 數據都做了落地處理 ,工具本身沒有對數據進行加載,內存開銷就很小,這一點非常重要!
- 易操作:啟動后,觀察遷移進度日志即可;
工具價值
redis-migration遷移工具不僅可以解決外部實例遷往網易私有云redis集群、私有云redis集群橫向擴容的問題,也可以解決外部redis集群的擴容問題, 具有通用價值 。比如:一個客戶端分片的分布式redis集群,通過redis-migration工具(外加一個數據分片代理程序,比如twemproxy)將數據實時同步到新的集群,然后應用直接切到新集群上,集群橫向擴容完成,中間不丟失任何數據!
應用案例
網易私有云線上已經有多個應用使用redis-migration進行了數據遷移,包括外部實例遷移、私有云分布式redis集群擴容等,下圖為幾個典型的應用:

另外,網易新聞客戶端推薦系統約2T規模的redis數據,也將依賴redis-migration遷移到私有云redis集群上來,目前正處于資源準備階段。
四、競爭對手
豌豆夾redis數據遷移工具
使用go語言實現,數據在線轉發,沒有落地,比較吃內存,經過簡單測試發現遷移效率沒有redis-migration高,源碼見 : https://github.com/CodisLabs/redis-port
騰訊云redis數據遷移工具
騰訊云redis數據遷移工具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
分布式系統的橫向擴容歷來是很難實現的,對redis集群這種純內存數據庫也不例外,而redis-migration遷移工具是對分布式redis集群橫向擴容實現的一次實踐,事實證明效果比較理想!
歡迎補充和測試。