1. 程式人生 > >某網站Redis與MySql同步方案分析

某網站Redis與MySql同步方案分析

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)的簡單說明:

這裡寫圖片描述

原理:

  1. Master將資料庫增量更新記錄到二進位制日誌(binary log)中(這些記錄叫做二進位制日誌事件,binary log events,可以通過show binlog events進行檢視);
  2. Slave將Master的binary log events拷貝到它的中繼日誌(relay log);
  3. 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方案過程中的注意事項進行說明:

  1. MySql需要開啟binlog模式,此模式下導致MySql效能下降。
  2. MySql需要開啟binlog模式,此模式下導致MySql的binlog檔案激增。
  3. 在處理blob資料型別時,需要進行轉碼。

說明:

  1. 如果MySql本身需要使用主從複製,則必須開啟binlog。所以此種情況下,第一條無需在意。
  2. 為了防止因binlog檔案激增導致資料庫伺服器磁碟激增,可以設定MySql日誌的自動清理。可以參考:《MySql自動清除binary logs日誌
  3. 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());
    }
}

具體轉換成何種編碼,請根據專案情況進行調節。