大家好,欢迎来到IT知识分享网。
一、数据同步方式介绍
1.1 什么是数据同步?
数据同步:当数据库中的数据发生变化,需要保证数据库中间件(Redis和ES)的数据与数据库数据保持一致
1.2 数据库中间件数据同步常用方式
Change Data Capture(CDC)
:使用CDC技术从数据库中捕获数据更改,并将更改的数据发送到ES。CDC可以监视数据库的事务日志或使用其他方法来检测数据更改,然后将这些更改同步到ES中。这种方法可以确保ES中的数据与数据库中的数据保持一致。双写
:在进行数据更改时,同时更新数据库和中间件(ES、Redis)。应用程序在更新数据库之后,直接将相同的更改发送到中间件。这种方法确保了在数据更改期间数据库和中间件之间的一致性,但需要增加应用程序的开发和维护复杂性。- 定期同步:定期将数据库中的数据同步到ES中。可以使用定时任务或批处理作业定期将数据库中的数据导入ES。这种方法可能会导致ES和数据库之间的数据有一定的延迟,但可以确保最终一致性。
- 使用消息队列:将数据更改发送到消息队列,然后消费者应用程序将更改应用于数据库和ES。消息队列可以充当缓冲,以确保数据更改在数据库和ES之间传递,并最终保持一致性。
- 采用事件驱动架构:将数据库中的数据更改表示为事件,并使用事件驱动架构来处理这些事件。当数据更改发生时,触发相应的事件,然后使用事件处理程序将更改应用于数据库和ES。这种方法将业务逻辑与数据更改解耦,并支持更高度的可扩展性和灵活性。
无论选择哪种方法,都需要仔细考虑数据一致性和容错性。此外,必须监测和处理中间件和数据库之间的任何同步错误或故障,以确保数据的完整性和一致性。
二、数据双写/双删
2.1 数据双写同步实现
接口1:查询商品信息,使用redis做缓存
接口2:根据关键字搜索商品信息,使用es搜索引擎
接口3:添加新的商品,通过双写操作同步redis、es
- 整合MyBatis-Plus
- 添加依赖
- 配置数据源
- 启动类添加
@MapperScan
- 配置和es的数据源
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/数据库名?charactorEncoding=utf-8 username: 你的mysql账号 password: 你的mysql密码 redis: host: 你的redis端口 port: 6379 默认6379 database: 0 password: 你的redis密码,若没有则忽略 elasticsearch: rest: uris: http://你的es的ip:9200 username: 你的es账号 password: 你的es密码
- Spring容器注入ES的客户端对象
@Configuration public class ESConfig { @Value("${spring.elasticsearch.rest.uris}") private String uris; @Value("${spring.elasticsearch.rest.username}") private String username; @Value("${spring.elasticsearch.rest.password}") private String password; @Bean public RestHighLevelClient getRestHighLevelClient(){ System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"+uris); int index1 = uris.indexOf("://"); int index2 = uris.lastIndexOf(":"); String protocol = uris.substring(0, index1); String host = uris.substring(index1+3,index2); String port = uris.substring(index2+1); HttpHost httpHost = new HttpHost(host, Integer.parseInt(port), protocol); RestClientBuilder restClientBuilder = RestClient.builder(httpHost); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder); return restHighLevelClient; } }
2.2.4 商品添加接口实现
保证redis和数据库数据的一致性:双写
@Override public ResultVO<Product> saveProduct(Product product) {
try{
int i = productMapper.insert(product); if(i>0){
String s = objectMapper.writeValueAsString(product); stringRedisTemplate.boundValueOps("product_" + product.getProductId()).set(s); } return new ResultVO<>(0,"添加商品成功",product); }catch (Exception e){
e.printStackTrace(); } return new ResultVO<>(1,"添加商品失败",null); }
2.2 数据双写问题分析
2.2.1 采用双写实现数据同步问题分析
我们采用双写操作——更新数据库的同时更新redis,因为写操作在完成数据库后更新之后再更新redis
问题:如果在更新数据库成功之后和更新redis成功之前,并发的读操作依然会读取到redis中未更新的数据——不能完全保证redis和数据库的强一致性
解决方案:
- 线程隔离(加锁),影响查询性能
- 将双写变为
先删后写
先删后写
2.2.2 采用先删后写实现数据同步问题分析
如果在修改线程删除redis之后写数据库之前,查询线程查询redis并查询数据库同时同步查询的数据到redis,在修改线程写数据库之后就会导致redis缓存数据与数据库数据不一致。
双删操作总结:
使用Redis做查询缓存,数据库更新操作保证Redis一致性: - 新增:只写数据库 - 修改:删除redis——修改数据库——删除redis - 删除:删除redis——删除数据库——删除redis
使用ES做搜索引擎,数据库更新操作保存ES一致性: - 新增:插入数据库——插入ES - 修改:删除ES——修改数据库——插入ES (可以搜索不到,但是不能搜索到修改之前的数据) - 删除:删除ES——删除数据库
三、CDC介绍
3.1 CDC概念
CDC,通过CDC工具监听数据库中数据的变化,同步更新到中间件
3.2 CDC实现方式
- 基于查询——通过查询操作对比数据的变化
- 基于binlog日志监听——需要MySQL开启日志监听功能
3.3 常见的CDC框架
- Canal:https://github.com/alibaba/canal
canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费
早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。 - Debezium:https://debezium.io/
- Flink CDC
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132160.html