Redis如何保证与数据库的一致性

redis与数据库不一致的两种情况

出现在高并发场景下,当有数据读和写的请求,就可能出现数据库与缓存不一致的情况

一、先操作删除缓存,再修改数据库数据的情况下
在这里插入图片描述

当缓存被线程一删除后,如果此时有新的读请求(线程二)发生,由于缓存已经被删除,这个读请求(线程二)将会去从数据库查询。如果此时线程一还没有修改完数据库,线程二从数据库读的数据仍然是旧值,同时线程二将读的旧值写入到缓存。线程一完成后,数据库变为新值,而缓存还是旧值。这就造成了数据库与缓存的不一致。

二、先修改数据库,再删除缓存
1、当数据库的数据被更新后,如果此时缓存还没有被删除,那么缓存中的数据仍然是旧值。如果此时有新的读请求(查询数据)发生,由于缓存中的数据是旧值,这个读请求将会获取到旧值。

2、当缓存刚好失效,这时有请求来读缓存(线程一),未命中缓存,然后到数据库中读取,在要写入缓存时,线程二来修改了数据库,而线程一写入缓存的是旧的数据,导致了数据的不一致。
在这里插入图片描述

解决办法

1、用redisson实现读锁和写锁

Redisson 是一个基于 Redis 的分布式 Java 对象存储和缓存框架,它提供了丰富的功能和 API 来操作 Redis 数据库。其中包括了读写锁的支持。

读写锁是一种常用的并发控制机制,它允许多个线程同时读取共享资源,但在写操作时互斥,只允许一个线程进行写操作

使用 Redisson 的读写锁方法:

  1. 获取读锁:通过 Redisson 的 RReadWriteLock 对象的 readLock() 方法获取读锁。在获取读锁后,可以并发读取共享资源,不会阻塞其他获取读锁的线程。

  2. 获取写锁:通过 Redisson 的 RReadWriteLock 对象的 writeLock() 方法获取写锁。在获取写锁后,其他获取读锁和写锁的线程将被阻塞,只有当前线程能够进行写操作。

  3. 释放锁:使用完读锁或写锁后,应该及时调用 unlock() 方法释放锁,以便其他线程可以获取锁并进行操作。在 Redisson 中,读锁和写锁都继承自锁对象 RLock,因此可以使用 RLock 的 unlock() 方法来释放锁。

下面是一个使用 Redisson 读写锁的示例:

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonReadWriteLockExample {
    public static void main(String[] args) {
        // 创建 Redisson 客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
        
        // 获取读写锁
        RReadWriteLock rwLock = redisson.getReadWriteLock("myLock");
        RLock readLock = rwLock.readLock();
        RLock writeLock = rwLock.writeLock();
        
        try {
            // 获取读锁并进行读操作
            readLock.lock();
            // 读取共享资源
            
            // 获取写锁并进行写操作
            writeLock.lock();
            // 写入共享资源
        } finally {
            // 释放锁
            writeLock.unlock();
            readLock.unlock();
        }
        
        // 关闭 Redisson 客户端
        redisson.shutdown();
    }
}

通过 Redisson 的 RReadWriteLock 对象获取读锁和写锁,并在需要的代码段中进行相应的操作。执行完操作后,使用 unlock() 方法释放锁,最后关闭 Redisson 客户端。

2、异步通知可以保证Redis双写一致性

在这里插入图片描述

在更新数据库数据时,同时发送一个异步通知给Redis,让Redis知道数据库数据已经更新,需要更新缓存中的数据。这个过程是异步的,不会阻塞数据库的更新操作。

当Redis收到异步通知后,会立即删除缓存中对应的数据,确保缓存中没有旧数据。这样,即使在这个过程中有新的读请求发生,也不会读取到旧数据。等到数据库更新完成后,Redis再次从数据库中读取最新的数据并缓存起来。

这种异步通知的方式,可以确保Redis中的数据与数据库中的数据保持一致,避免出现数据不一致的情况。

需要注意的是,异步通知可能会出现延迟或者丢失的情况,因此需要做好异常处理和重试机制,确保数据的准确性。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值