新聞資訊  快訊  焦點  財經  政策  社會
互 聯 網   電商  金融  數據  計算  技巧
生活百科  科技  職場  健康  法律  汽車
手機百科  知識  軟件  修理  測評  微信
軟件技術  應用  系統  圖像  視頻  經驗
硬件技術  知識  技術  測評  選購  維修
網絡技術  硬件  軟件  設置  安全  技術
程序開發  語言  移動  數據  開源  百科
安全防護  資訊  黑客  木馬  病毒  移動
站長技術  搜索  SEO  推廣  媒體  移動
財經百科  股票  知識  理財  財務  金融
教育考試  育兒  小學  高考  考研  留學
您當前的位置:首頁 > IT百科 > 站長技術 > 服務器

禧云Redis跨機房雙向同步實踐

時間:2019-11-20 10:52:25  來源:  作者:

一、項目介紹

Rotter是禧云自主研發的跨機房redis雙向同步解決方案(下文簡稱為方案),具有零侵入、高吞吐量、低延時、高堆積能力等特點。當前版本支持Sentinel模式和單點模式Redis架構。從2019年Q2上線至今,服務于三個獨立業務線,線上運行穩定,同步延時基本在50ms以內。

1.1 系統架構

整個Redis跨機房雙向同步系統分為三層:

  • 控制臺Manager
  • 節點發現和數據傳輸層(ZK+Redis)
  • 數據同步層Rotter

系統架構如圖1-1

禧云Redis跨機房雙向同步實踐

圖1-1

其中,

  • Manager負責任務配置、數據展示、監控報警等,各機房獨立部署;
  • ZK為跨機房集群,A機房為Leader節點,B機房為Follow節點。ZK在方案中負責Rotter節點的注冊發現和任務調度。
  • 多活Redis在方案中扮演數據隊列的角色,降低了Manager和Rotter節點之間的耦合度。
  • Rotter是Redis同步任務的執行者,包含replicator和sync兩個角色。
  • replicator是國人開源的基于JAVA語言的redis主從協議實現者redis-replicator,負責解析redis節點指令。
  • sync負責redis指令跨機房寫入,處理同步回環,同步指令監控等。

1.2 同步流程

Rotter中采用鏈式處理同步數據,任何一個Filter返回失敗,該指令將不會同步。鏈式流程如圖1-2

禧云Redis跨機房雙向同步實踐

圖1-2

  1. ParseEventFilter:格式化同步指令;生成指令回環校驗key;賦值指令所屬DB;過濾Rotter自身產生的指令
  2. DBFilter:過濾掉不需要同步的DB
  3. KeyFilter:過濾掉不需要同步的KEY
  4. CircleSyncFilter:過濾掉回環指令和刪除保護指令
  5. MultiThreadFilter:多線程分發,提高同步效率
  6. OvertimeFilter:經過隊列積壓,判斷該指令是否已經過期
  7. DeleteKeyFilter:生成刪除保護KEY
  8. RateLimitFilter:限流,包括帶寬和指令數
  9. SendTargetFilter:執行目標redis寫入
  10. MonitorFilter:監控和上報正在同步的指令
  11. ComputeRateFilter:計算同步速率、帶寬、隊列積壓長度等

二、背景&目標

2.1 背景

異地多活系統自2018年Q2上線以來,各核心業務系統都已陸續接入異地雙活架構。異地多活已經成為我司保障服務高可用的常規武器。在我司的異地雙活解決方案中,首先通過動態域名和阿里云全局流量管理服務達到用戶流量的初步劃分,然后在Nginx層根據流量規則對用戶流量精準轉發,確保同一個用戶的請求能夠穩定地請求到同一個機房,從而保證兩個機房不會同時修改同一份數據。

即便如此,可靠的跨機房的數據同步仍然是雙活方案最基本要求。多活業務依賴非多活業務數據或者流量調度時都依賴數據同步服務。MySQL層的數據同步是通過阿里巴巴開源的otter完成的,Redis的跨機房雙向數據同步業內缺少合適解決方案。

沒有Redis雙向同步,往往需要犧牲業務的時效性,或者業務系統需要寫一些額外的代碼來處理緩存數據缺失的情況;另外,用戶會話數據需要落到MySQL中來確保流量調度時用戶無感知。

2.2 目標

基于背景部分闡述,我們可以知道,我司的跨機房Redis同步方案是跨機房異地多活方案的一個延伸,最根本的訴求就是讓我司的業務不會因為接入多活系統受到限制,讓我們工程師可以像實現單機房業務一樣實現多機房業務。

所以,在項目啟動之初就定下以下目標:

  1. 零侵入:業務系統不需要做任何改造就能接入
  2. 高吞吐量:基于現有業務峰值Tps乘以10,得出TPS要達到1萬
  3. 低延時:我司的多活業務不會出現跨機房讀取數據的情況,所以定的目標延時低于1s。實際情況延時在50ms左右
  4. 高堆積能力:基于跨機房網絡的不確定性,當網絡閃斷時能夠保證指令不丟失
  5. 高可用性:當網絡故障或者Redis宕機恢復時,同步任務能自動恢復
  6. 可配置性:業務系統可以自由定制需要同步哪些Key

三、技術選型

要達到一條Redis指令寫入兩個機房的Redis節點,可以從client端、代理層、server端三個層面分別實現。

先說client端解決方案面臨的問題:

  1. 我們需要提供一套統一的工具包,為每個指令提供一個是否需要同步到另一機房的參數;
  2. 我們可能還需要為工具包提供同步寫另一機房還是異步寫另一機房的參數;
  3. 寫另一機房失敗本機房數據是否需要回滾?
  4. 現在java業務系統使用jedis和redisson都有,適配難度大,且不利于客戶端版本升級

所以,客戶端側解決方案被第一個否決了。

再來看代理層解決方案會面臨哪些問題:

  1. 代理的性能怎么樣,代理本身的延時高不高?
  2. 我司現有Redis架構基本都是Sentinel模式的,代理層解決方案每接入一個同步任務就需要重新調整Redis架構和網絡,對運維同學不太友好
  3. 代理層解決方案同樣面臨同步寫其他機房還是異步寫其他機房,寫其他機房失敗怎么處理的問題。
  4. 開源界的Redis代理項目基本都不是基于java語言的,對于我們團隊來說二次開發的難度較大。

代理層解決方案應該能解決我們的問題,但也不是特別理想。

接下來看看如果我們從服務端側解決,會面臨哪些問題:

  1. 我們需要解析到客戶端的指令
  2. 需要解決同步回環問題:A -> B -> A

解決掉這兩個問題,一個Redis指令寫入兩個機房的基本上就解決了。所以我們選擇了從server端同步來實現。Redis主從協議的實現采用的國人開源的redis-replicator;回環同步問題下文中會詳細講到。

四、實現細節

本節會詳細介紹一些具體問題的解決方案。

4.1 網絡架構

我司在網絡層用雙機房雙向VPN隧道打通局域網,北京到上海的網絡延時穩定在30ms左右。這樣我們的Redis節點就不需要暴露在公網,數據安全這塊就不需要考慮了。

4.2 同步回環

同步回環是指同一條指令在兩個Redis節點重復執行,看系統架構圖的下面一截:圖4-2

禧云Redis跨機房雙向同步實踐

圖4-2

如果不對同步指令加任何干預,業務寫的一條指令會在A、B兩個機房的Redis節點上無限循環執行:

  1. 業務系統在A機房redis-A寫入指令 set a 1
  2. A機房replicator-A作為redis-A的從節點接收到指令set a 1
  3. rotter-A將指令set a 1寫入B機房redis-B
  4. B機房replicator-B作為redis-B的從節點接收到指令set a 1
  5. rotter-B將指令set a 1寫入A機房redis-A …

為了打破這個循環,我們采用了增加一個輔助key的辦法:

  1. 業務系統在A機房redis-A寫入指令 set a 1
  2. A機房replicator-A作為redis-A的從節點接收到指令set a 1
  3. rotter-A MD5(set a 1) 得到circle-key-md5,拼裝成指令setex circle-key-md5 120 1
  4. rotter-A將指令setex circle-key-md5 120 1和指令set a 1一起寫入B機房redis-B
  5. B機房replicator-B作為redis-B的從節點接收到指令setex circle-key-md5 120 1 和set a 1
  6. rotter-B直接忽略circle-key指令
  7. rotter-B在本機房執行del circle-key-md5,如果成功說明是回環KEY,不需要同步至A機房

4.3 高吞吐量

要提高吞吐量我們首先需要知道性能瓶頸在哪。從上面處理回環同步的問題我們可以看到,同步流程中存在兩處需要業務Redis交互:

  1. Rotter收到同步指令之后需要在本機房執行del circle-key-md5來判斷當前指令是否為循環指令
  2. Rotter將同步指令和circle-key-md5寫入另一機房Redis

這里我們有兩個武器:多線程和Pipeline。

多線程:

引入多線程的同時會引入另外一個問題:如何保證指令的順序性?

順序性的保證在同步回環校驗階段和跨機房寫入階段略有不同。

同步回環階段我們只要得到指令是否為回環指令就行,和各指令之間校驗的順序沒關系,但需要保證在往下一環節發送的時候是有序的。所以我們是采用線程隊列實現的。關鍵代碼如下 :

……

寫目標機房階段我們需要嚴格保證執行順序,假如業務系統執行兩條指令set a 1和del a,如果同步時執行順序反了,會對業務系統產生不可預估的后果。但如果是兩個不同的key,大部分場景下是可以交換執行順序的。

所以我們自己實現了一個簡單的有序線程池,對同步的key取hash后再取mod,mod值相同的指令放在同一線程執行,這樣就保證了同一個key的執行順序一定是有序的。同時我們還支持將指定的key分配到同一個線程執行,滿足業務系統存在key之間相互依賴的場景。

Pipeline:

通過redis pipeline批量執行指令能夠大量的減少Rotter和Redis的交互次數,但也會帶來一個問題:不能將指令阻塞在pipeline中太久而增加同步延時,所以我們需要另外一個線程來觸發提交pipeline數據,目前Rotter采取的策略是每100條或者10ms發送一次。

4.4 高堆積能力

由于跨機房網絡的不確定性,網絡隔離隨時可能發生。為了保證同步指令不丟失,我們需要把指令寫到磁盤文件中,等到網絡恢復時再從磁盤隊列讀出來寫到目標機房,

為了保證同步效率,我們這里使用的是磁盤和內存混合隊列MixBlockingQueue

……

下面我們再來看看磁盤隊列是怎么實現的

磁盤隊列包含兩個文件:數據文件和索引文件。數據結構如圖4-4

禧云Redis跨機房雙向同步實踐

圖4-4

其中索引文件是定長的18字節:

  • redisOffset(8字節):存儲每條同步指令在復制積壓緩沖區的offset,每次重新啟動同步任務時可以通過二分查找確定是否需要從磁盤中繼續讀取指令。
  • dataOffset(8字節):存儲指定在磁盤文件中的位置
  • dataLength(2字節):存儲當前指令的長度

由于索引文件中數據長度為2字節,所以單條指令長度最大值為32kb,超過此大小則會丟棄這條指令

五、其他問題

5.1 Rotter連接業務Redis時造成Redis全量dump而影響業務系統

背景知識一:復制積壓緩沖區

復制積壓緩沖區是一個保存在主節點的一個固定長度的先進先出的隊列,默認大小 1MB。 這個隊列在 slave 連接時創建。這時主節點響應寫命令時,不但會把命令發送給從節點,也會寫入復制緩沖區。他的作用就是用于部分復制和復制命令丟失的數據補救。通過 info replication 可以看到相關信息。

背景知識二:Redis主從同步協議

禧云Redis跨機房雙向同步實踐

 

背景知識三:Redis全量同步流程

  1. slave發送Replication ID, offset到master
  2. master開啟一個進程執行bgsave,生成RDB文件。在此期間所有新的指令都會緩存到當前slave的輸出緩沖區中
  3. master把RDB文件發送到slave
  4. slave把RDB文件加載到內存
  5. master把輸出緩沖區中的指令增量同步到slave

在這個過程中,如果Redis存儲數據量過大,會導致生成RDB文件大,對磁盤IO的壓力會非常大,一旦磁盤IO打滿會導致Redis進入假死狀態,進程沒掛,客戶端拿不到連接。

我們的解決方案有兩點:

  1. 優先連接Redis從節點,減少bgsave對業務的影響
  2. 配置同步任務時可以選擇是否忽略全量dump,當忽略全量dump時,Rotter會通過redis info命令拿到復制積壓緩沖區的offset,從最新的位置開始增量同步。

5.2 如何防止Rotter同步反向污染源Redis數據

Redis數據同步和MySQL數據同步是相互獨立的,當MySQL同步延時較大時可能會出現Redis數據反向污染的情況。案例如下:

禧云Redis跨機房雙向同步實踐

圖5-2

如圖5-2流程所示,Rotter同步會造成業務系統原本已經A機房刪掉了記錄a又被同步到A機房Redis了。

為了解決這個問題,我們引入了刪除保護的概念:一段時間(默認2分鐘)內在A機房刪除的數據不會從B機房同步到A機房。具體做法如下:

  1. 圖5-2中第3步Rottor-A將del a指令同步到B機房之前,生成刪除保護指令setex rotter:delete:a 120 1,將這兩條指令都寫入redis-B
  2. 圖5-2中第6步Rotter-B同步指令set a oldValue先執行 exists rotter:delete:a,返回成功判定key a是剛被刪除的,不會同步A機房

原文出處: http://www.cnblogs.com/zhengyun_ustc/p/rotter.html



Tags:Rotter   點擊:()  評論:()
聲明:本站部分內容來自互聯網,內容觀點僅代表作者本人,如有任何版權侵犯請與我們聯系,我們將立即刪除。
▌相關評論
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
▌相關推薦
一、項目介紹Rotter是禧云自主研發的跨機房Redis雙向同步解決方案(下文簡稱為方案),具有零侵入、高吞吐量、低延時、高堆積能力等特點。當前版本支持Sentinel模式和單點模式Red...【詳細內容】
2019-11-20   Rotter  點擊:(18)  評論:(0)  加入收藏
相關文章
    無相關信息
最新更新
欄目熱門
欄目頭條
31选7开奖11185