应用场景
分布式架构中,数据同步常常是个大问题。例如,mysql中的数据,可能在ElasticSearch有一份索引,在redis有一份缓存,在Nginx有一份缓存,这时候只要你修改了mysql中的数据,其他微服务并没有更新,这时候数据就不一致了,所以为了解决数据同步问题,我一般会考虑两种情况来解决。1、定时更新
适用于对数据一致性不那么敏感的业务场景,例如首页广告图、热度榜等。显而易见,这么做的好处是对性能的考验没那么大,可以选定隔一段时间更新一次,或者等并发量小的时候再更新。2、实时更新
而对于数据需要一致性的业务场景,可以通过监控数据库变动,再通过MQ消息队列来通知其他微服务更新数据。优缺点跟定时更新恰好相反,它的优点可以实时更新数据,缺陷就是如果数据变动频繁,对这套架构的性能、稳健性(例如消息丢失,更新失败等情况)将会是极大的考验。
canal
canal是纯Java开发,基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持MySQL。最早是阿里巴巴为了同步杭州和美国的双机房而开发的数据同步中间件。
一、实现原理
二、Canal部署
因为Canal是阿里开发的,中央仓库没有,所以需要自己安装到maven仓库。
1、下载解压
https://github.com/alibaba/canal/releases/tag/canal-1.0.24
2、点进这个目录下输入mvn install命令安装进maven
3、修改MySQL路径下的/etc/my.cnf文件
[mysqld]
log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复
4、重启mysql服务
5、使用root账号创建用户并授权
create user canal@'%' IDENTIFIED by 'canal'; GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%'; FLUSH PRIVILEGES;
数据同步
1、创建微服务并导入依赖
com.xpand
starter-canal
0.0.1-SNAPSHOT
2、创建监听类
//标识监听类
@CanalEventListener
public class BusinessListener {
@Autowired
private RabbitTemplate rabbitTemplate;
//监控指定表
@ListenPoint(schema = "goods", table = {"tb_spu"})
public void adUpdate(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
System.err.println("商品数据发生变化");
//获取修改前数据
for(CanalEntry.Column column: rowData.getBeforeColumnsList()) {
//把字段为position的数据通过MQ发送
if(column.getName().equals("position")){
rabbitTemplate.convertAndSend("",
RabbitMQConfig.AD_UPDATE_QUEUE,
column.getValue());
break;
}
}
//获取修改后数据
for(CanalEntry.Column column: rowData.getAfterColumnsList()) {
//把字段为position的数据通过MQ发送
if(column.getName().equals("position")){
rabbitTemplate.convertAndSend("",
RabbitMQConfig.AD_UPDATE_QUEUE,
column.getValue());
break;
}
}
}
}
最终架构