Redis【 Redis企业级解决方案(Redis脑裂、缓存预热、缓存穿透、缓存击穿、缓存雪崩、Redis开发规范、数据一致性 )】(七)-全面详解(学习总结---从入门到深化)

 

目录

Redis企业级解决方案_Redis脑裂

 什么是Redis的集群脑裂

 解决方案

 Redis企业级解决方案_缓存预热

 缓存冷启动

 缓存冷启动场景

 Redis企业级解决方案_缓存穿透

 概念

布隆过滤器 

扫描二维码关注公众号,回复: 15443396 查看本文章

什么是布隆过滤器

 代码实现

Redis企业级解决方案_缓存击穿

 ​编辑

 Redis企业级解决方案_缓存雪崩

 概念

 Redis企业级解决方案_Redis开发规范

 value设计

拒绝bigkey

 命令使用

 客户端使用

Redis企业级解决方案_数据一致性 


Redis企业级解决方案_Redis脑裂

 什么是Redis的集群脑裂

Redis的集群脑裂是指因为网络问题,导致Redis Master节点跟Redis slave节点和Sentinel集群处于不同 的网络分区,此时因为sentinel集群无法感知到master的存在,所以将slave节点提升为master节点。

 

 注意:

此时存在两个不同的master节点,就像一个大脑分裂成了两个。集群脑裂问题中,如果客户端还在基于原来的master节点继续写入数据,那么新的Master节点将无法同步这些数据,当网络问题 解决之后,sentinel集群将原先的Master节点降为slave节点,此时再从新的master中同步数据, 将会造成大量的数据丢失。

 解决方案

redis.conf配置参数:

min-replicas-to-write 1
min-replicas-max-lag 5

 1.Redis的集群脑裂是指_____问题。网络

 2.Redis的集群脑裂通过配置____命令解决。min-replicas-max-lag

 Redis企业级解决方案_缓存预热

 缓存冷启动

缓存中没有数据,由于缓存冷启动一点数据都没有,如果直接就对外提供服务了,那么并发量上来 Mysql就裸奔挂掉了。

 

 缓存冷启动场景

新启动的系统没有任何缓存数据,在缓存重建数据的过程中,系统性能和数据库负载都不太好,所以最好是在系统上线之前就把要缓存的热点数据加载到缓存中,这种缓存预加载手段就是缓存预热。

 

 

 1.Redis技术中缓存预热主要解决____问题。 缓存冷启动

 Redis企业级解决方案_缓存穿透

 概念

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别 大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

 

 

 解决方案

1. 对空值缓存:如果一个查询返回的数据为空(不管数据是否存在),我们仍然把这个空结果缓存, 设置空结果的过期时间会很短,最长不超过5分钟。

2. 布隆过滤器:如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起 来,然后通过比较确定。

布隆过滤器 

什么是布隆过滤器

布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效 地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。

 

 

 代码实现

引入hutool包

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.17</version>
</dependency>

java代码实现

// 初始化 注意 构造方法的参数大小10 决定了布隆过滤器BitMap的大小
BitMapBloomFilter filter = new BitMapBloomFilter(10);
filter.add("123");
filter.add("abc");
filter.add("ddd");

boolean abc = filter.contains("abc");
System.out.println(abc);

1.布隆过滤器是一种数据库结构,底层是_____。 bit数组

2.Redis技术中缓存穿透主要指____问题。 缓存和数据库中都没有的数据

Redis企业级解决方案_缓存击穿

 

 概念

某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最 终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库

 

 解决方案

 代码实现

public String get(String key) throws InterruptedException {

    String value = jedis.get(key);
    // 缓存过期
    if (value == null){
        // 设置3分钟超时,防止删除操作失败的时候 下一次缓存不能load db
        Long setnx = jedis.setnx(key + "mutex", "1");
        jedis.pexpire(key + "mutex", 3 * 60);
        // 代表设置成功
        if (setnx == 1){
            // 数据库查询
            //value = db.get(key);
            //保存缓存
            jedis.setex(key,3*60,"");
            jedis.del(key + "mutex");
            return value;
    }else {
            // 这个时候代表同时操作的其他线程已经load db并设置缓存了。 需要重新重新获取缓存
            Thread.sleep(50);
            // 重试
            return get(key);
        }
    }else {
            return value;
     }
}

 1.Redis技术中缓存击穿指______问题。 缓存中没有但数据库中有的数据

 2.Redis技术中缓存击穿如何解决。加互斥锁

 Redis企业级解决方案_缓存雪崩

 概念

缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发 到DB,DB瞬时压力过重雪崩。

缓存正常从Redis中获取,示意图如下:

 缓存失效瞬间示意图如下:

 解决方案

过期时间打散:既然是大量缓存集中失效,那最容易想到就是让他们不集中生效。可以给缓存的过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效。

热点数据不过期:该方式和缓存击穿一样,也是要着重考虑刷新的时间间隔和数据异常如何处理的情况。

加互斥锁: 该方式和缓存击穿一样,按 key 维度加锁,对于同一个 key,只允许一个线程去计算, 其他线程原地阻塞等待第一个线程的计算结果,然后直接走缓存即可。

 加锁排队代码如下:

public Object GetProductListNew(String cacheKey) {
        int cacheTime = 30;
        String lockKey = cacheKey;
        // 获取key的缓存
        String cacheValue = jedis.get(cacheKey);
        // 缓存未失效返回缓存
        if (cacheValue != null) {
                return cacheValue;
            } else {
                // 枷锁
                synchronized(lockKey) {
                // 获取key的value值
                cacheValue = jedis.get(cacheKey);
                if (cacheValue != null) {
                        return cacheValue;
                } else {
                //这里一般是sql查询数据
                // db.set(key)
                // 添加缓存
                jedis.set(cacheKey,"");
            }
        }
        return cacheValue;
    }
}

注意: 加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。

 1.Redis技术中缓存雪崩指____问题。缓存中数据大批量到过期时间

 2.Redis技术中缓存雪崩____解决。 缓存数据的过期时间设置随机

 Redis企业级解决方案_Redis开发规范

 

 示例

# 表名 主键 主键值 存储列名字
set user:user_id:1:name xiaoton
set user:user_id:1:age 20
#查询这个用户
keys user:user_id:9*

 value设计

拒绝bigkey

防止网卡流量、慢查询,string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。

 命令使用

1、禁用命令

禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐 进式处理。

2、合理使用select

redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线 程处理,会有干扰。

3、使用批量操作提高效率

 4、不建议过多使用Redis事务功能

Redis的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot 上。

 客户端使用

1. Jedis :https://github.com/xetorthio/jedis 重点推荐

2. Spring Data redis :https://github.com/spring-projects/spring-data-redis 使用Spring框架时推荐

3. Redisson :https://github.com/mrniko/redisson 分布式锁、阻塞队列的时重点推荐

1、避免多个应用使用一个Redis实例 

不相干的业务拆分,公共数据做服务化。

2、使用连接池

可以有效控制连接,同时提高效率,标准使用方式:

执行命令如下:
Jedis jedis = null;
try {
        jedis = jedisPool.getResource();
        //具体的命令
        jedis.executeCommand()
    } catch (Exception e) {
        logger.error("op key {} error: " + e.getMessage(), key, e);
    } finally {
        //注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
        if (jedis != null)
                jedis.close();
    }

 1.Redis技术中下列符合key设计__。user:id.1.age

Redis企业级解决方案_数据一致性 

 缓存已经在项目中被广泛使用,在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。

 

 缓存说明: 从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。

 三种更新策略

      1. 先更新数据库,再更新缓存

      2. 先删除缓存,再更新数据库

      3. 先更新数据库,再删除缓存

先更新数据库,再更新缓存

这套方案,大家是普遍反对的。为什么呢?

   线程安全角度

        同时有请求A和请求B进行更新操作,那么会出现

          (1)线程A更新了数据库

          (2)线程B更新了数据库

          (3)线程B更新了缓存

          (4)线程A更新了缓存 这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。 这就导致了脏数据,因此不考虑。

 先删缓存,再更新数据库

 先更新数据库,再延时删缓存

 

 1.Redis技术中哪一种保证数据一致性最合理。设置过期时间

猜你喜欢

转载自blog.csdn.net/m0_58719994/article/details/131361175