redis总结

一、缓存穿透

大量查询不存在的数据,从而跳过缓存直接查询数据,造成数据库崩溃

解决方案

1.对空值进行缓存
就是将不存在的数据访问结果, 也存储到缓存中并设置过期时间,避免缓存访问的穿透。最终不存在商品数据的访问结果也缓存下来。有效的避 免缓存穿透的风险。
缺点:占用内存,可能会发生不一致的问题,一般情况redis查询为空还是会重新查询数据库的,所以不推荐

2. 布隆过滤器
将数据库中所有的查询条件,放入布隆过滤器中,当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查;如果判断请求查询不存在,直接丢弃。

二、缓存雪崩

redis中大量的key集体过期

解决方案
1. 在设置具体的缓存生效时间的时候, 加上一个随机的区间因子, 比如 说 5~10 分钟之间来随意选择失效时间;
2. 提前预估 DB 能力, 如果缓存挂掉,数据库仍可以在一定程度上抗住流量 的压力 这三个策略能够有效的避免短时间内,大批量的缓存失效的问题。

三、缓存击穿

redis中的某个热点key过期,但是此时有大量的用户访问该过期key

解决方案

1.使用互斥锁
就是在缓存失效的时候(判断拿出来的值为空),不是立即去查询数据库,
而是先使用缓存工具的某些带有操作成功返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
     	 if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
               value = db.get(key);
               redis.set(key, value, expire_secs);
               redis.del(key_mutex);
           } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
               sleep(50);
               get(key);  //重试
           }
       } else {
           return value;      
       }
 }

四、双写一致性

1、延时双删

写数据库之前删除一次,写完数据库后,隔500ms再删除一次。

在这里插入图片描述

有了缓存删除方案之后,我们在回顾一下高并发下的场景问题:

1.请求d先过来,把缓存删除了。但由于网络原因,卡顿了一下,还没来得及写数据库。
2.这时请求c过来了,先查缓存发现没数据,再查数据库,有数据,但是旧值。
3.请求c将数据库中的旧值,更新到缓存中。
4.此时,请求d卡顿结束,把新值写入数据库。
5.一段时间之后,比如:500ms,请求d将缓存删除。 这样看确实解决了缓存不一致的问题,但是为什么我们非得等一会在删除缓存呢? 请求d卡顿结束,把新值写入数据库后,请求c将数据库中的旧值,更新到缓存中。
此时,如果请求d删除太快,在请求c将数据库中的旧值更新到缓存之前,就已经把缓存删除了,这次删除就没任何意义。我们必须要搞清楚,我们之所以要再删除一次缓存的原因是因为c请求导致缓存中更新了数据库中旧值,我们需要把这个旧值删除掉,所以必须要在请求c更新缓存之后,再删除缓存,才能把旧值及时删除了,删除删除太快,可能后面。

现在解决了一个问题之后,又遇到一个问题:如果第二次删除缓存时,删除失败了该怎么办呢?

2、通过消息队列解决缓存删除失败的问题

在高并发的业务场景中,mq(消息队列)是必不可少的技术之一。它不仅可以异步解耦,还能削峰填谷。对保证系统的稳定性是非常有意义的。

mq的生产者,生产了消息之后,通过指定的topic发送到mq服务器。然后mq的消费者,订阅该topic的消息,读取消息数据之后,做业务逻辑处理。

使用mq重试的具体方案如下:

当用户操作写完数据库,但删除缓存失败了,产生一条mq消息,发送给mq服务器。
mq消费者读取mq消息,重试5次删除缓存。如果其中有任意一次成功了,则返回成功。如果重试了5次,还是失败,则写入死信队列中。
当然在该方案中,删除缓存可以完全走异步。即用户的写操作,在写完数据库之后,不用立刻删除一次缓存。而直接发送mq消息,到mq服务器,然后有mq消费者全权负责删除缓存的任务。
在这里插入图片描述

因为mq的实时性还是比较高的,因此改良后的方案也是一种不错的选择。

五、redis 持久化机制(怎么保证 redis 挂掉之后再重启数据可以进行恢复)

RDB 快照持久化 -每隔一段时间备份内存的数据到磁盘上

Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备 份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性 能),还可以将快照留在原地以便重启服务器的时候使用。

AOF(append-only file)持久化

与快照持久化相比,AOF 持久化 的实时性更好。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:appendonly yes
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入硬盘中的 AOF 文件。AOF 文件 的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:
在 redis.conf 配置文件中存在三种不同的 AOF 持久化方式,可通过 appendfsync 配置项修改:
always #每次有数据修改发生时都会写入 AOF 文件,这样会严重降低 Redis 的速度
everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘
no #让操作系统决定何时进行同步

RDB 与 AOF 混用

在我们的Redis 4.0 后,提供了AOF与RDB的混用机制,也叫混合持久化。
开启混合持久化需要在config文化中手动开启

改为 yes 开启混合持久化
aof-use-rdb-preamble yes

六、redis 基本数据结构

string incrBy生成唯一主键,用作计数器,统计在线人数等等,可以存储二进制数据如使用它来存储图片等。
hash 存放键值对,一般可以用来存某个对象的基本属性信息,例如,用户信息,商品信息等
list 链表,列表类型,可以用于实现消息队列,也可以使用它提供的range命令,做分页查询功能。
set 集合,可以用作去重功能,例如用户名不能重复等,另外,还可以对集合进行交集,并集操作,来查找某些元素的共同点
Sorted Set 有序集合 常用命令: zadd,zrange,zrem,zcard 等 和 set 相比,sorted set 增加了一个权重参数 score,
使得集合中的元素能够按 score 进行有序排列。 举例: 在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度 的消息排行榜)等信息,适合使用 Redis 中的 SortedSet 结构进行存储

七、redis的1w条的插入和更新有什么区别

插入的效率较高,不需要查找指定的键并修改对应的值

插入操作:
插入操作用于将新的键值对存储到Redis中。
如果指定的键已经存在,则插入操作将会失败,返回错误信息。需要注意处理插入已存在键的情况。
插入操作的性能较高,因为不需要对现有数据进行修改和比较。

更新操作:
更新操作用于修改已存在键的值。
更新操作要求指定的键必须存在,否则更新操作将会失败。需要确保键存在于Redis中。
更新操作的性能较插入操作略低,因为它需要找到指定键并修改对应的值。

redis为什么效率高,线程,数据结构,网络模型,aio, nio, bio, 为什么这么设计?如何处理高并发

Redis之所以具有高效性,主要有以下几个方面的设计和特点:

内存存储:Redis将数据存储在内存中,通过跳过磁盘IO等耗时操作,大大提高了数据访问的速度。内存读写速度快、无需磁盘IO的开销,使得Redis具备了出色的性能。
纯内存操作:Redis的操作都是基于内存的,没有频繁的磁盘读写操作,避免了磁盘IO带来的性能瓶颈。
数据结构:Redis提供了丰富的数据结构,如字符串、哈希、列表、集合和有序集合等。这些数据结构经过优化,使得Redis可以灵活高效地处理不同类型的数据,满足各种场景的需求。
单线程模型:Redis采用单线程模型,即单个线程处理所有客户端的请求。这样可以避免多线程间的竞争和锁的开销,简化了并发控制和数据一致性的处理,提高了系统的稳定性和性能。
非阻塞IO:Redis使用非阻塞IO模型,即通过异步非阻塞的方式处理客户端请求和网络通信。这样可以充分利用CPU资源,提高系统的并发处理能力。
网络模型:Redis采用了基于事件驱动的网络模型,通过事件循环机制监听和处理网络事件。这样可以减少线程切换开销和上下文切换的消耗,提高了系统的响应速度和并发处理能力。
AIO、NIO和BIO:Redis在网络通信方面使用了非阻塞IO(包括AIO和NIO),避免了线程阻塞等待IO操作完成的情况。这样可以提高网络IO的效率,充分利用系统资源。

处理高并发的方法可以有以下几点:

水平扩展:通过增加Redis节点(主从复制或集群)来增加处理能力,充分利用多台服务器的资源。
集群方案:使用Redis集群来分片和分布数据,以提高并发处理能力和数据存储容量。
缓存优化:合理使用Redis的缓存功能,将频繁访问的数据缓存到内存中,减轻数据库的负载。
异步操作:对于耗时的操作,可以使用异步方式进行处理,如异步任务队列、消息队列等,提高系统的并发性能。
数据模型优化:根据业务需求和数据访问模式,合理设计和选择Redis的数据结构和存

遗留问题
redis的集合有没有限制,限制是多少
redis的1w条的插入和更新有什么区别
redis为什么效率高,线程,数据结构,网络模型,aio, nio, bio, 为什么这么设计?如何处理高并发

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值