当前位置: 首页>后端>正文

Redis分布式锁原理及性能优化

一、什么是分布式锁

在单体架构中,系统只有一个,系统所用的内存和进程也只有一个,多个线程可以共享同一份数据。这样只要使用java提供的锁机制就可以解决并发访问带来的问题,但是分布式系统中,系统是多个,并且所使用的内存也是不同的,每个系统也都有独立的进程,这样Java提供的锁就没办法解决分布式系统中的并发访问问题。因此就需要引入分布式锁来解决分布式系统中共享资源访问的问题。

1.2 分布式锁的特性

1.要保证同一时刻内,只有一个服务获取到这个锁
2.这把锁要能重入,在某些业务下会出现同一把锁的重入
3.具备锁续命,保证高并发下不会因锁的时效问题引起数据错误
4.具有非阻塞式获取锁,在获取锁失败后立刻返回

1.3 基于Redisson实现的分布式锁

Redisson中分布式锁的架构:
Redis分布式锁原理及性能优化,第1张

关于Redisson分布式锁的使用:

private Integer setInfo(Long key){
    // 获取分布式锁
    RLock lock = redisson.getLock("Ext_Info:" + key);
    // 加锁
    lock.lock();
    try{
        // 业务处理
        Product product = productDao.get(key);
        return 1;
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        // 解锁
        lock.unlock();
    }
    return  -1;
}

1.4 分布式锁失效问题

当主从或集群机构的主节点挂掉后,该节点存储的分布式锁信息可能会丢失。而当从节点选举成新节点后,其它线程又可以对新的主节点进行添加分布式锁信息,这就会引起并发安全问题。

为了解决这个问题,就引入了redlock。
redlock的逻辑就是向多个节点写入加锁的信息,如果写入成功,加代表加锁成功。但是如果写入的节点丢失了锁的信息,仍然是会出现分布式锁失效问题。
还有一点就是性能问题,我们使用redis就是为了它的高性能,但是使用redlock后每次加锁都要写入多个节点,这就会降低redis性能,这样还不如使用zookeeper。


Redis分布式锁原理及性能优化,第2张

二、Redisson实现分布式锁源码剖析

加锁的核心逻辑:
Redis分布式锁原理及性能优化,第3张
加锁成功后的锁续命逻辑:
Redis分布式锁原理及性能优化,第4张
其它线程加锁失败后的逻辑:
Redis分布式锁原理及性能优化,第5张
解锁核心逻辑:
Redis分布式锁原理及性能优化,第6张

三、分布式锁的优化

对于读多写少的业务,可以使用readwirte锁:

public Product update(Product product) {
    Product productResult = null;
    // 获取分布式锁
    RReadWriteLock readWriteLock = redisson.getReadWriteLock(LOCK_PRODUCT_UPDATE_PREFIX + product.getId());
    // 写锁
    RLock writeLock = readWriteLock.writeLock();
    // 加锁
    writeLock.lock();
    try {
        productResult = productDao.update(product);
        // 设置过期时间
        redisUtil.set(productResult.getId(), JSON.toJSONString(productResult),
                genProductCacheTimeout(), TimeUnit.SECONDS);
    } finally {
        // 释放锁
        writeLock.unlock();
    }
    return productResult;
}

redisson实现的读写锁,大体上和上面的分布式锁逻辑相同,只是加了一个mode,用于区分是读还是写。对于读读而言,就等于是锁的重入,不会阻塞;对于读写、写写操作,就会阻塞保证并发的安全。

四、缓存问题

1、什么是缓存击穿?

当同一时刻有大量的缓存失效,就会导致大量的请求打到数据库,会造成数据库压力过大甚至宕机。
解决办法:在给缓存数据设置过期时间时,增加一个随机的扰动因子,避免让大量的缓存数据都同一时刻失效。

2、什么是缓存穿透?

缓存层和数据库都没有数据,每次请求都会落到数据库,如果是高并发场景下,就会引起数据的压力剧增,甚至宕机。
解决办法:
1、对于不存在的数据,可以在缓存层面设置对应key的空值
2、布隆过滤器,向布隆过滤器中添加key时,会先使用多个hash函数进行运算,然后定位到布隆过滤器的数组中某个下标。当某个key查询布隆过滤器数据时,会同样使用多个hash函数进行运算,然后得到数组中的下标位置。

3、什么是缓存雪崩?

缓存层的作用就是分担数据库层面的压力,如果缓存层宕机,大量的请求就直接打到数据库,高并发下数据库有可能宕机。
解决办法:
1、确保缓存层的高可用,比如搭建集群、主从架构
2、在后端应用上设置限流或服务降级


https://www.xamrdz.com/backend/3fv1936660.html

相关文章: