4.4 缓存同步策略

一、数据同步策略

  1. 缓存数据同步的常见方式有三种:

    1. 设置有效期:给缓存设置有效期,到期后自动删除。再次查询时更新

      1. 优势:简单、方便

      2. 缺点:时效性差,缓存过期之前,可能不一致

      3. 场景:更次年频率较低,时效性还要求低的业务

    2. 同步双写:再修改数据库的同时,直接修改缓存

      1. 优势:时效性强,缓存与数据库强一致

      2. 缺点:有代码侵入,耦合度高

      3. 场景:对一致性、时效性要求较高的缓存数据

    3. 异步通知:修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据

      1. 优势:低耦合,可以同步通知多个缓存服务

      2. 缺点:时效性一般,可能存在中间不一致的状态

      3. 场景:时效性要求一般,有多个服务需要同步

  2. 异步通知:

    1. 基于MQ的异步通知

      基于MQ的异步通知

    2. 基于Canal的异步通知

      基于Canal的异步通知

二、安装Canal

  1. Canal,译为水道、管道、渠道,canal是阿里巴巴旗下的一款开源项目,基于Java开。基于数据库增量日志解析,提供增量数据订阅&消费。github地址:https://github.com/alibaba/canal

  2. Canal是基于Mysql的主从同步来实现的

    1. Mysql master将数据变更写入二进制日志(binary log),其中记录的数据叫binary log events

    2. Mysql slave将master的binary log events拷贝到它的中继日志(realy log)

    3. Mysql slave重放realy log 中的时间,将数据变更反映他自己的数据

  3. Canal就是把自己伪装成为Mysql的一个slave节点,从而监听master的binary log变化。再把得到的变化信息通知给Canal的客户端,从而完成对其他数据库的同步

  4. 安装和配置Canal,参考附录2

三、监听Canal

  1. Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端

  2. 官方开源的客户端比较麻烦,这里推荐第三方开源的canal-starter客户端:https://github.com/NormanGyllenhaal/canal-client

    1. 引入坐标地址

      <dependency>
          <groupId>top.javatool</groupId>
          <artifactId>canal-spring-boot-starter</artifactId>
          <version>1.2.1-RELEASE</version>
      </dependency>
    2. 编写配置

      canal:
        destination: heima  # canal实例名称,需要跟canal-server运行时设置的destinations一致
        server: ip:端口  # Canal地址
    3. 编写监听器,监听Canal消息

      @CanalTable("tb_item")  // 指定监听的表
      @Component
      public class ItemHandler implements EntryHandler<Item> {  // Item指定表关联的泛型
          
          // 监听数据库的增操作消息
          @Override
          public void insert(Item item) {
              // 新增数据
          }
          
          // 监听数据库的改操作消息
          @Override
          public void update(Item before, Item after) {
              // 新增数据
          }
          
          // 监听数据库的删操作消息
          @Override
          public void delete(Item item) {
              // 删除数据
          }
          
      }
    4. Canal推送给canal-client的是被修改的这一行数据(row),而我们引入的canal-client则会帮我们把行数据封装到实体类中,这个过程中需要数据库与实体的映射关系,需要用到JPA的几个注解

      @Data
      @TanleNAme("tb_item")
      public class Item {
          
          @TableId(type = IdType.AUTO)
          @Id  // 标记id主键
          private Long id;
          
          @Column(name = "name") // 标记表中与属性名不一致的字段
          private String name;
          
          @TableField(exist = "false")
          @Transient    // 非当前表的字段
          private Integer stock;
          
      }

四、总结

多级缓存总结

最后更新于

这有帮助吗?