Redis-06 Redis面试高频问题、Redis日常开发规避问题

众所周知,使用Redis可极大提升查询效率,也可提供分布式锁解决方案,本章节将根据日常开发中可能出现的实际场景重点讲解使用Redis的架构设计相关问题,以及如何设计高效的分布式锁。

1,缓存穿透

查询缓存和数据库中都没有的数据,导致请求都下沉至数据库,造成数据库压力过大。

常用场景:

1,程序判断机制有误,并发场景下大量查询下沉至数据库;

2,黑客攻击,通过缓存穿透方式打垮数据库,造成系统崩溃。

解决方案:

1,前端程序做限频率

1,后端程序做基本判断。ID<0直接返回;

2,缓存空对象并设置过期时间。可使相同数据第二次请求时快速返回;

3,使用布隆过滤器。通过bitmap将所有对象ID缓存至布隆过滤器,请求先通过布隆过滤器判断对象是否存在,不存在则直接返回,存在再去Redis或数据库拿取数据。

2,缓存击穿

查询缓存中有但数据库没有的数据,导致请求都下沉至数据库,造成数据库压力过大。

常用场景:

1,大批量缓存数据在同一时间或临近时间失效,导致查询下沉;

2,少量缓存数据失效,大并发请求该数据,同样导致查询下沉。

解决方案:

1,查询时为缓存续命,每次查询添加或重置过期时间,引导冷热数据分离;

2,设置缓存的过期时间时,在时间基数上添加随机时间,造成缓存过期时间不同。

3,缓存雪崩

解释一:Redis服务宕机,所有查询直接流向数据库,导致数据压力变大,查询变慢甚至宕机;

解释二:大批量数据在同一时间或临近时间段内失效,后续大量查询流向数据库,导致数据压力变大,查询变慢甚至宕机。

解决方案:同缓存击穿

4,热点key重建优化

常用场景:

某个热点消息或热点商品的缓存过期后,大并发请求查询,可能造成多个线程重建缓存,导致程序和Redis服务压力过大

解决方案:

重建缓存时加分布式锁,并使用双重验证法。

加分布式锁可使得只能有一个线程重建缓存;双重验证可使得其余线程执行时直接从缓存获取。伪代码如下:

java 复制代码
String get(String key) {
    // 从Redis中获取数据
    String value = redis.get(key);
    if (value != null){
        return value;
    }

    // 如果value为空, 则开始重构缓存
    // 只允许一个线程重建缓存, 使用nx, 并设置过期时间ex
    String lockKey = "lock:key:" + key;
    if (redis.set(lockKey , "1", "ex 180", "nx")) {
        
        // 双重验证。从Redis中获取
        value = redis.get(key);

        if (value ==null){
            // 从数据源获取数据
            value = db.get(key);
            // 回写Redis, 并设置过期时间
            redis.setex(key, timeout, value);
        } else {
            // 重置过期时间
            redis.expire(key, timeout);
        }      
        
        // 删除锁
        redis.delete(mutexKey);
    }
    // 其他线程休息50毫秒后重试
    else {
        Thread.sleep(50);
        get(key);
    }

    return value;
}

5,缓存与数据库双写不一致

如下图:线程1在写完数据库后,写Redis前因程序或网络导致延迟,线程2在延迟期间通过数据库查询到该值,更新后写至数据库和Redis。线程1再写Redis时,写入的就是错误的旧值。

解决方案:

使用redisson的读写锁,读写锁对Redis的读读不互斥,读写/写写互斥,保证在同一时刻,只能有一个线程写Redis。

同上例,若使用了读写锁,线程1在写Redis时卡顿,线程2对Redis的写操作将会阻塞,等待线程1写完Redis并释放锁后,线程2才能获取锁再写Redis,保证了Redis数据为最新值。

注意:

1,双写不一致现象为小概率事件。并发量不高的系统,几乎不用考虑;

2,Redis数据一般都会设置过期时间,如果可以容忍短期数据不一致,也不用考虑。

相关推荐
深蓝电商API31 分钟前
分布式事务在跨境交易中的解决方案
分布式·跨境电商·代购系统·反向海淘·代购平台·跨境代购
RainyJiang1 小时前
谱写Kotlin协程面试进行曲-进阶篇(第二乐章)
面试·kotlin·android jetpack
wyt5314292 小时前
Redis的安装教程(Windows+Linux)【超详细】
linux·数据库·redis
vpk1123 小时前
Docker Compose 安装 Redis
redis·docker·容器
Moment4 小时前
前端工程化 + AI 赋能,从需求到运维一条龙怎么搭 ❓❓❓
前端·javascript·面试
独自破碎E4 小时前
【面试真题拆解】你知道ThreadLocal是什么吗
java·jvm·面试
我真会写代码5 小时前
从入门到精通:Kafka核心原理与实战避坑指南
分布式·缓存·kafka
我真会写代码6 小时前
Redis高频面试题(含标准答案,覆盖基础+进阶+实战)
数据库·redis·缓存
黄俊懿6 小时前
【架构师从入门到进阶】第二章:系统衡量指标——第一节:伸缩性、扩展性、安全性
分布式·后端·中间件·架构·系统架构·架构设计
一叶飘零_sweeeet6 小时前
击穿 Kafka 高可用核心:分区副本、ISR 机制与底层原理全链路拆解
分布式·架构·kafka