某网站Redis与MySql同步方案分析

后续文章: 通过Canal保证某网站的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的不一致
3MySql的UDF通过数据库中的触发器(Trigger)调用UDF(user defined function,自定义的函数库),来触发对Redis的相应操作自定义的函数库需要我们基于MySql的API进行开发(C++)(阿里早期做法)
4Gearman+PHP+MySql UDF通过借用已经比较成熟的MySql UDF,将MySql数据首先放入Gearman中,然后通过一个自己编写的PHP Gearman Worker,将数据同步到Redis一般使用在PHP的开发中
5Open-Replicator解析binlogOpen Replicator是一个用Java编写的MySql binlog分析程序。Open Replicator 首先连接到MySql,然后接收和分析binlog,根据binlog的分析结果进行缓存操作。主动读取binlog,实时性保证不够,整体解决方案不够成熟
6Canal解析binlogCanal主要是基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,核心基本就是模拟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());
    }
}

具体转换成何种编码,请根据项目情况进行调节。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页