Redis相关问题(进阶篇)

文章介绍了Redis的单线程模型为何能保持高效,包括内存操作、数据结构简单、多路复用和非阻塞IO等因素。同时,讨论了Redis的持久化机制,如RDB和AOF,以及如何确保数据安全性。此外,提到了Redis的事务特性、主从复制实现读写分离和哨兵机制应对主机故障。最后,文章讨论了Redis的键过期策略以及缓存问题的解决方案,如缓存穿透、缓存击穿和缓存雪崩。
摘要由CSDN通过智能技术生成

一、Redis线程模型

提出问题:Redis 是单线程模型还是多线程模型?

Redis读写速度快,为什么快?

  • Redis6.x 版本之前是真正意义上的单线程

  • Redis6.x 引入了多线程,将客户端网络请求,由一些线程来负责完成

  • 数据的读写操作仍然使用的是单线程,单线程操作不会出现并发安全问题

为什么设计成单线程模型速度也很快?

1.基于内存操作:Redis 的所有数据都在内存中,因此所有的运算都是内存级别的,所以它的性能比高.

2.数据结构简单:Redis 的数据结构是为自身专门量身打造的,而这些数据结构的查找和操作的时间复杂度都是 O(1).

3.多路复用和非阻塞 IO:Redis 使用 IO 多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程来处理多个情况,从而减少线程切换带来的开销,同时也避免了 IO 阻塞操作,从而大大地提高了 Redis 的性能.

4.避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的开销,而且单线程不会导致死锁的问题发生.

  • hash表可以在 O(1)的时间内计算出 hash 值并且找到对应的 entry 位置,entry

里面是一个 key 指针和 value 指针,其实还有其他信息。这也是 redis 之所以性能高

的原因之一.

二、Redis持久化

为什么redis要提出持久化概念?

  • 因为redis数据平时存储在内存中,一旦机器故障,断电,数据可能就会丢失,

redis也提供了数据持久化机制,把内存中的数据根据一定的规则,写入到硬盘中

去,开启定时任务,每天的某一时间,把redis的数据写入到mysql中。Redis 还

为我们提供了持久化的机制,分别是RDB(Redis DataBase)和 AOF(Append Only File)。

RDB方式(Redis DataBase)

  • RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,保存在dump.rdb文件中。

数据集快照:内存中有许多key-value key1-value1---->dump.rdb文件

  • RDB方式是redis默认的持久化方式,不需要配置开启,默认是支持的.

  • 里面有触发RDB保存快照的条件,如下配置:

save 900 1 :表示 900 秒钟内至少 1 个键被更改则进行快照。

save 300 10 :表示 300 秒内至少 10 个键被更改则进行快照。

save 60 10000 :表示 60 秒内至少 10000 个键被更改则进行快照。

  • 在redis客户端模式中,使用shutdown save 命令在关闭redis服务时,保存快照

  • 重新启动redis服务时,把dump.rdb文件内容还原回来.

AOF方式(Append Only File)

  • AOF是以记录日志的方式来记录所有写操作的命令

set name jim 执行一次 记录一次

set name tom

name : tom

appendfsync always 每次修改都会 sync 消耗性能

appendfsync everysec 每秒执行一次 sync,可能会丢失这1s 的数据(默认)

定期结合mysql方式

人为的定期将数据写入到mysql中。

三、Redis事务

  • redis事务,是将多条命令放入到一个队列中,保证多条命令,在同一个事务中执行,

不受其他客户端的影响.

  • multi 开启事务

命令1

命令2

命令3 把命令加入到一个队列中,并没有立即执行

  • exec 执行事务

  • 但是事务不保证同一事物中多条命令执行的原子性,即使命令有错误也会添加到队列中,执行报错也不影响其他命令执行.

四、主从复制

  • Redis在大型项目(互联网电商),为了保证系统稳定,有一台服务作为主机,有多台服务作为从机,主机负责写入数据,将数据同步到多台从机,从机负责读操作,实现读写分离

  • 即使是主机故障,也可以从多台从机中,选举出一台服务作为主机(哨兵机制),这样必将存在数据冗余和服务冗余.

  • 负载均衡:

在主从复制的基础上,配合读写分离,可以由主节点提供写服务, 由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载;尤其是在写少读多的 场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。

  • redis伪集群:

可以在一台机器上,配置多个redis端口,启动多个redis实例.

五、哨兵机制

哨兵是一个独立的任务,独立运行,定期的向集群中的redis发送信息,如果收不到信息,就表明redis 服务有问题,可以通过一套选举机制,在多台从机中选取一台作为主机,当主机故障恢复后,临时主机又 变为了从机.

六、key过期策略

在设置key时,可以为key设置一个有效时间,当时间到了后,redis有一套机制,可以来删除过期的key.

  1. 立即删除

在设置key时,创建一个回调函数,当key的时间到了之后,立即执行回调函数,删除key,不浪费内存空 间,到期即删除. 如果有大量的key同时到期,删除会占用cpu时间,所以对CPU不太友好.

  1. 惰性删除

到期后不立即删除.在下次使用此key时,判断是否到期,到期后就删除,对内存不友好,浪费内存空间

  1. 定时删除

将过期的key记录下来,定期的对过期的key的进行删除.

可以看到,第二种为被动删除,第一种和第三种为主动删除,且第一种实时性更高。每隔一段时间执 行一次删除操作,并通过限制删除操作执行的时长和频率,来减少删除操作对 cpu 的影响。另一方面 定时删除也有效的减少了因惰性删除带来的内存浪费.

  • redis 使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用.

七、缓存穿透、缓存击穿、缓存雪崩

  • 开始使用redis时,redis可以用来缓存数据,已达到对mysql的压力缓解,也不是说用了redis,就不会出现问题了,在一些极端情况下也是会出现问题的.

缓存穿透

概念:

有一个数据,在数据库中本身就不存在,这样redis中也就没有了,那么每次查询的请求依然会到达 mysql数据库(黑客可能利用此漏洞去攻击,把数据库弄跨)

解决办法:

1.将这个空对象设置到缓存里面去,下次再请求时,就可以从缓存里边获取了,这种情况我们一般会为 空对象设置一个较短的过期时间.

2.对参数进行校验,不合法的参数进行拦截

缓存击穿

概念:

数据库中有数据,在某一时间节点上,某个热点key到期了,此时刚好有大量的请求到达,如果没有任 何的限制,同时查询redis,但是redis中没有(过期了),请求就会到达mysql,导致mysql被压垮

解决办法:

1.将热点key设置为永不过期(比如秒杀活动:让key在活动结束后再过期)

2.加锁:上面的现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请 求上使用一个互斥锁来锁住它,其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数 据,然后将数据放到 redis 缓存起来。后面的线程进来发现已经有缓存了,就直接走缓存.

缓存雪崩

概念:

在高并发状态下,大量的key过期或者缓存出现故障,导致大量请求到达mysql,导致mysql垮掉.

解决办法:

1.设置key的失效时间随机,不要同时失效.

2.把热点key放在不同的从机

3.设置不过期

4.定时任务,将快过期的key,重新放入到缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值