新闻资讯

如何配置 Redis 数据库的多层缓存同步

2025-02-23

在当今的软件开发中,缓存技术对于提升系统性能至关重要。Redis 作为一款高性能的内存数据库,在多层缓存同步配置方面有着出色的表现。配置 Redis 数据库的多层缓存同步,主要有设置有效期、同步双写和异步通知这三种常见方式,每种方式各有优劣,适用于不同的业务场景。下面将详细介绍这三种方式及其具体配置步骤。

设置有效期
原理
给缓存设置有效期,到期后自动删除。当再次查询时,系统会更新缓存。这种方式实现起来非常简单,只需在设置缓存时指定一个过期时间即可。例如,在使用 Redis 的 SET 命令时,可以同时使用 EX 参数来设置过期时间(单位为秒)。
优势
实现简单、方便,几乎不需要额外的代码逻辑。在很多对数据时效性要求不高的场景下,这种方式能够满足基本需求,同时减少了缓存与数据库不一致的时间窗口。
缺点
时效性较差,在缓存过期之前,缓存数据与数据库数据可能存在不一致的情况。如果业务对数据的实时性要求较高,这种方式可能就不太适用。
场景
适用于更新频率较低,时效性要求低的业务。比如一些静态数据的缓存,像商品分类信息等,这些数据不经常变动,即使缓存数据与数据库数据在短时间内存在差异,也不会对业务造成太大影响。
同步双写
原理
在修改数据库的同时,直接修改缓存。以 Java 代码为例,当执行数据库更新操作时,紧接着就执行 Redis 的缓存更新操作。例如,使用 Spring Data Redis 框架,在更新数据库的方法中,添加如下代码来更新 Redis 缓存:
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void updateDataInDatabaseAndCache(YourDataObject data) {
// 更新数据库
yourDatabaseRepository.update(data);
// 更新Redis缓存
redisTemplate.opsForValue().set("yourKey", data);
}
优势
时效性强,能够保证缓存与数据库强一致。只要数据库更新成功,缓存也会立即更新,不存在数据不一致的中间状态。
缺点
有代码侵入,耦合度高。每次数据库操作都需要同时处理缓存操作,这使得代码的维护和扩展变得复杂。而且,如果在更新缓存过程中出现异常,可能会导致数据库更新成功但缓存未更新的情况。
场景
适用于对一致性、时效性要求较高的缓存数据。比如电商系统中商品的库存信息,库存数据的准确性至关重要,任何不一致都可能导致超卖等问题,所以适合采用同步双写的方式。
异步通知
原理
修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据。而异步实现又可以基于 MQ(消息队列)或者 Canal 来实现。

基于 MQ 的异步通知
1.原理:商品服务完成对数据的修改后,只需要发送一条消息到 MQ 中。缓存服务监听 MQ 消息,然后完成对缓存的更新。例如,使用 Kafka 作为 MQ,在商品服务中,当数据更新后,发送消息到 Kafka 的指定主题:
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;

public void updateDataAndSendMessage(YourDataObject data) {
// 更新数据库
yourDatabaseRepository.update(data);
// 发送消息到Kafka
kafkaTemplate.send("yourTopic", data.toString());
}
在缓存服务中,监听 Kafka 主题并更新缓存:
@KafkaListener(topics = "yourTopic", groupId = "yourGroup")
public void listenAndUpdateCache(String message) {
YourDataObject data = parseDataFromMessage(message);
// 更新Redis缓存
redisTemplate.opsForValue().set("yourKey", data);
}
1.优势:解耦了数据库操作和缓存更新操作,低耦合,可以同时通知多个缓存服务。即使某个缓存服务出现故障,也不会影响数据库操作和其他服务。
2.缺点:时效性一般,可能存在中间不一致状态。因为消息在 MQ 中传递以及缓存服务处理消息都需要一定的时间,在这段时间内,缓存与数据库可能存在不一致。
3.场景:适用于时效性要求一般,有多个服务需要同步的场景。比如在一个大型的分布式系统中,有多个服务都依赖于某个数据的缓存,当数据更新时,通过 MQ 通知各个服务更新缓存。
基于 Canal 的通知
1.原理:Canal 是阿里巴巴旗下的一款开源项目,基于 Java 开发,基于数据库增量日志解析,提供增量数据订阅 & 消费。Canal 把自己伪装成 MySQL 的一个 slave 节点,从而监听 master 的 binary log 变化。当商品服务完成商品修改后,业务直接结束,没有任何代码侵入。Canal 监听 MySQL 变化,当发现变化后,立即通知缓存服务,缓存服务接收到 canal 通知,更新缓存。
2.引入依赖:使用 GitHub 上的第三方开源的 canal - starter 客户端,在 Maven 项目的 pom.xml 文件中添加如下依赖:

top.javatool canal-spring-boot-starter 1.2.1-RELEASE

1.编写配置:在 Spring Boot 的配置文件 application.properties 中添加 Canal 的配置信息,例如:
canal.server.host=127.0.0.1
canal.server.port=11111
canal.server.destination=yourDestination
canal.server.username=yourUsername
canal.server.password=yourPassword
1.修改 Item 实体类:Canal 推送给 canal - client 的是被修改的这一行数据 (row),而引入的 canal - client 会帮我们把行数据封装到 Item 实体类中。这个过程中需要知道数据库与实体的映射关系,要用到 JPA 的几个注解,通过 @Id、@Column 等注解完成 Item 与数据库表字段的映射。例如:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tb_item")
public class Item {
@Id
private Long id;
@Column(name = "item_name")
private String itemName;
// 其他字段及getter、setter方法
}
1.编写监听器:通过实现EntryHandler接口编写监听器,监听 Canal 消息。注意两点:实现类通过@CanalTable("tb_item")指定监听的表信息;EntryHandler的泛型是与表对应的实体类。示例代码如下:
import com.alibaba.otter.canal.protocol.CanalEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.javatool.canal.spring.annotation.CanalTable;

@Component
@CanalTable("tb_item")
public class ItemHandler implements EntryHandler {
@Autowired
private RedisHandler redisHandler;
@Autowired
private Cache<Long, Item> itemCache;

@Override
public void insert(Item item) {
    // 写数据到JVM进程缓存
    itemCache.put(item.getId(), item);
    // 写数据到redis
    redisHandler.saveItem(item);
}

@Override
public void update(Item before, Item after) {
    // 写数据到JVM进程缓存
    itemCache.put(after.getId(), after);
    // 写数据到redis
    redisHandler.saveItem(after);
}

@Override
public void delete(Item item) {
    // 删除数据到JVM进程缓存
    itemCache.invalidate(item.getId());
    // 删除数据到redis
    redisHandler.deleteItemById(item.getId());
}

}
1.优势:代码零侵入,数据库操作与缓存更新完全解耦,系统的可维护性和扩展性更好。
2.缺点:同样存在时效性一般,可能出现中间不一致状态的问题。并且 Canal 的配置和维护相对复杂一些。
3.场景:适用于对代码侵入性要求严格,时效性要求一般的大型分布式系统。

通过以上对三种 Redis 数据库多层缓存同步方式的详细介绍,开发者可以根据具体的业务需求和系统架构,选择最合适的方式来配置 Redis 多层缓存同步,从而提升系统的性能和稳定性。


拓展阅读:
1.什么是缓存命中率:缓存命中率是指在缓存系统中,请求的数据能够直接从缓存中获取的比例,缓存命中率越高,说明缓存的利用效率越高。
2.Redis 的持久化方式有哪些:Redis 的持久化方式主要有 RDB(Redis Database)和 AOF(Append Only File),RDB 是将内存中的数据定期写入磁盘,AOF 是将每条写命令追加到一个日志文件中 。
3.什么是消息队列:消息队列是一种异步通信机制,用于在不同系统或组件之间传递消息,解耦应用程序,提高系统的可扩展性和可靠性。

新闻资讯
热门专题
最新专题
友情链接