某網站Redis與MySql同步方案分析
阿新 • • 發佈:2019-02-16
1.編寫目的
某網站專案引入了redis快取技術,如何保證Redis與MySql的資料一致性是開發人員需要首要解決的問題。
本文主要包括以下內容:
- Redis與MySql的資料一致性方案彙總與選取
- Canal解析binlog方案簡介
- 其他Redis開發原則
2.方案彙總與選取
下面展示了幾種常見的Redis與MySql資料一致性的方案:
序號 | 方案 | 方案簡述 | 評價 |
---|---|---|---|
1 | 手動同步一 | 對於讀操作,先讀redis,有則返回,無則讀取MySql,並插入Redis。對於寫操作,先寫MySql,再讀Redis。 | 直觀簡單,但是每次資料操作都需要手動維護快取和資料庫的一致性 |
2 | 手動同步二 | 對於讀操作,先讀redis,有則返回,無則讀取MySql,並插入Redis。對於插入操作,先插入MySql,再寫入cache。對於更新和刪除操作,先刪除cache,再操作MySql。 | 直觀簡單,但是每次資料操作都需要手動維護快取和資料庫的一致性。高併發情況下,會出現db與cache的不一致 |
3 | MySql的UDF | 通過資料庫中的觸發器(Trigger)呼叫UDF(user defined function,自定義的函式庫),來觸發對Redis的相應操作 | 自定義的函式庫需要我們基於MySql的API進行開發(C++)(阿里早期做法) |
4 | Gearman+PHP+MySql UDF | 通過借用已經比較成熟的MySql UDF,將MySql資料首先放入Gearman中,然後通過一個自己編寫的PHP Gearman Worker,將資料同步到Redis | 一般使用在PHP的開發中 |
5 | Open-Replicator解析binlog | Open Replicator是一個用Java編寫的MySql binlog分析程式。Open Replicator 首先連線到MySql,然後接收和分析binlog,根據binlog的分析結果進行快取操作。 | 主動讀取binlog,實時性保證不夠,整體解決方案不夠成熟 |
6 | Canal解析binlog | Canal主要是基於資料庫的日誌解析,獲取增量變更進行同步,由此衍生出了增量訂閱&消費的業務,核心基本就是模擬MySql中Slave節點請求。 | 阿里開源專案,比較成熟的解決方案。 |
方案分析與選取:
- 方案1和2都需要開發人員去手動維護Reids和MySql之間的同步。
- 方案3需要編寫UDF。
- 方案4一般用在PHP開發中。
- 方案5實時性較差。
- 本專案採用方案6:通過Canal解析binlog。
3.Canal解析binlog簡介
2.2.binlog
binlog,全稱binary log,即MySql的二進位制日誌檔案。
binlog用於記錄mysql的資料更新或者潛在更新(比如DELETE語句執行刪除而實際並沒有符合條件的資料),在mysql主從複製中就是依靠的binlog。
2.3.MySql主從複製
下圖是對MySql的主從複製(Master/Slave)的簡單說明:
原理:
- Master將資料庫增量更新記錄到二進位制日誌(binary log)中(這些記錄叫做二進位制日誌事件,binary log events,可以通過show binlog events進行檢視);
- Slave將Master的binary log events拷貝到它的中繼日誌(relay log);
- Slave重做中繼日誌中的事件,將資料庫增量更新反映到自己的資料庫中。
2.4.Canal原理
下圖是對MySql的主從複製(Master/Slave)的簡單說明:
原理:
1. Canal模擬MySql Slave的互動協議,偽裝自己為MySql Slave,向MySql Master傳送dump協議
2. MySql Master收到dump請求,開始推送binary log給Slave(也就是Canal)
3. Canal解析binary log物件(原始為byte流)
4.其他Redis開發原則
下面列出一些已經確定的Redis開發原則:
- 所有的寫操作(插入、更新、刪除)都訪問MySql。
- 所有的讀操作都訪問cache。
- 通過Canal解析MySql的binlog同步Redis來保持資料一致性。
- 提供一個初始化全部快取資料的方法:initCache。
- Redis的KEY命名規範:專案名稱-模組名稱-物件名稱-主鍵id。例如:baidu-news-user-0000000001。
5.注意事項
通過一段時間的使用,現將使用Canal解析binlog方案過程中的注意事項進行說明:
- MySql需要開啟binlog模式,此模式下導致MySql效能下降。
- MySql需要開啟binlog模式,此模式下導致MySql的binlog檔案激增。
- 在處理blob資料型別時,需要進行轉碼。
說明:
- 如果MySql本身需要使用主從複製,則必須開啟binlog。所以此種情況下,第一條無需在意。
- 為了防止因binlog檔案激增導致資料庫伺服器磁碟激增,可以設定MySql日誌的自動清理。可以參考:《MySql自動清除binary logs日誌》
- Canal在讀取了binlog的資料之後,會進行判斷屬於那種資料型別。這時,如果此欄位屬於blob欄位,則進行轉碼即可,虛擬碼如下:
//判斷每個欄位
for (Column column : columns) {
//如果欄位型別為blob,則進行轉碼
if ("blob".equals(column.getMysqlType())) {
json.put(column.getName(), new String(column.getValue().getBytes("ISO-8859-1"),"gbk"));
}else{//其他欄位直接將欄位名和值放到json串中
json.put(column.getName(), column.getValue());
}
}
具體轉換成何種編碼,請根據專案情況進行調節。