关于redis同步数据库的问题

有一个这样的需求,redis连接异常(网络问题,或者是缓存重启)以后,就需要通过数据库查询,那么应该怎么实现,什么时候往数据库里写,什么时候数据库往缓存里写呢等,又不会因为过多查询数据库而导致性能降低?

一般都会有一套缓存策略 最简单的就是redis找不到去db里面找 找到了再写进去 而且缓存重启后 数据量大的话是需要缓存预热的

读的时候先查redis 无法命中的时候才查数据库。同时查询结果写入redis 写的时候 ,先写入数据库 然后再更新redis 。然后还可以做一些定期sync同步等

"缓存是一种提高系统性能的有效手段,MyBatis自带的缓存机制可以满足大部分场景的需求,但是在分布式系统中,使用Redis等第三方缓存更为合适。"
Redis可以使用Hash数据结构来缓存表的数据,其中Hash的key可以是表名,value可以是一个包含表中所有行数据的Map对象。例如,缓存一个user表的数据可以使用以下命令:

HSET user id1 {"id":"id1","name":"Alice","age":20}
HSET user id2 {"id":"id2","name":"Bob","age":25}
HSET user id3 {"id":"id3","name":"Charlie","age":30}

其中,id1、id2、id3是user表中的主键,每个主键对应一个包含该行数据的Map对象。

为了保证数据一致性,可以使用以下两种方式:

  1. 在写入数据库时,同时更新Redis缓存。这样可以保证缓存中的数据与数据库中的数据一致。

  2. 使用缓存失效机制。当数据库中的数据发生变化时,可以通过一些手段(如数据库触发器、消息队列等)通知Redis缓存失效,下次查询时再从数据库中读取最新数据并更新缓存。这样虽然不能保证缓存中的数据与数据库中的数据完全一致,但可以保证数据的最终一致性。
    数据库触发器是一种在数据库中定义的特殊程序,它可以在数据库中的某个表上执行特定的操作(如插入、更新、删除等)时自动触发。通过在触发器中调用Redis的API,可以实现在数据库更新时同时更新Redis缓存的功能。例如,以下是一个MySQL数据库中的触发器示例:

CREATE TRIGGER user_insert AFTER INSERT ON user
FOR EACH ROW
BEGIN
EXECUTE 'HSET user ' || NEW.id || ' ' || NEW.data;
END;

该触发器会在user表中插入一条新数据时自动执行,将该数据写入Redis缓存中。
消息队列是一种用于在分布式系统中传递消息的机制,它可以将消息发送到一个或多个接收者,并确保消息的可靠传递。通过在消息队列中发送缓存失效的消息,可以实现在数据库更新时通知Redis缓存失效的功能。例如,以下是一个使用RabbitMQ消息队列实现缓存失效的示例:

// 发送缓存失效消息
channel.basicPublish(EXCHANGE_NAME, "cache.invalid", null, "user".getBytes());

// 接收缓存失效消息
channel.basicConsume("cache.invalid", true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String tableName = new String(body, "UTF-8");
redis.del(tableName);
}
});

该示例中,当数据库中的user表发生变化时,会向名为"cache.invalid"的消息队列发送一条消息,表示该表的缓存需要失效。同时,一个消费者会监听该队列,当接收到消息时会从Redis缓存中删除该表的数据。