美文网首页
Redis分布式锁原理及性能优化

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

作者: 枫叶红花 | 来源:发表于2023-02-02 11:44 被阅读0次

    一、什么是分布式锁

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

    1.2 分布式锁的特性

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

    1.3 基于Redisson实现的分布式锁

    Redisson中分布式锁的架构: image

    关于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。


    image.png

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

    加锁的核心逻辑: image 加锁成功后的锁续命逻辑: image 其它线程加锁失败后的逻辑: image 解锁核心逻辑: image

    三、分布式锁的优化

    对于读多写少的业务,可以使用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、在后端应用上设置限流或服务降级

    相关文章

      网友评论

          本文标题:Redis分布式锁原理及性能优化

          本文链接:https://www.haomeiwen.com/subject/mqwwhdtx.html