redis解析

redis

redis是单线程执行的IO多路复用模型

具体实现是redis基于Reactor 开发了文件事件处理器,

文件事件处理器:

img

Redis6.0 引入多线程主要是为了提高网络 IO 读写性能,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。

redis是怎么知道哪个数据过期了的,redis保存了一个map,key是redis中的某个键,value是过期时间。

数据过期了怎么淘汰:

惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。

定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响

但是,仅仅依靠这两个的话,还是有oom的风险的,

所以还提供了LRU算法

内存淘汰机制:

  1. allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)

  2. volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

  3. 还有一种直接拒绝新写入的数据

持久化机制:

RDP:快照机制,快照的话就是某个时间点下的数据副本

默认配置的话,是你相对时间内改变数据很频繁的话,他就很快的执行快照命令BGSAVE

AOF:

三种模式:

每当你改变数据的话,他就把命令写入aof文件中,

一秒钟同步一次,

让操作系统去决定

AOF重写机制

  • AOF重写

aof 文件记录的是每一条redis命令,有时候我们会对某一个key进行多次set,中间会产生很多条命令,但是结果只有一个。

set name 1
...
set name 12
set name 123
...
set name 1234
set name 12345

例如我们执行了上述命令,aof 文件会记录着每一条命令。在redis重启时,会逐条执行上述的命令。但是其实可以精简为set name 12345,其余的几条命令其实没有意义。AOF重写就是实现了这个功能。

相关配置:

auto-aof-rewrite-percentage 100  # 指当前aof文件比上次重写的增长比例大小,达到这个大小就进行 aof 重写
auto-aof-rewrite-min-size 64mb  # 最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了

以上配置的意思是:

在 aof 文件小于64mb的时候不进行重写,当到达64mb的时候,就重写一次。重写后的 aof 文件可能是10mb。上面配置了auto-aof-rewrite-percentage 100,即 aof 文件到了20mb的时候,又开始重写一次。以此类推。

AOF 是在后台自动重写(redis会fork一个子进程来进行备份,保证主进程不会阻塞),也可以人为执行命令 bgrewriteaof 重写 AOF。


  • 使用子进程来进行AOF重写时会遇到的问题

问题:

子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。

解决方案:

要知道redis是怎么处理这个问题的,需要先了解下AOF重写的具体实现:

img

AOF文件重写过程与RDB快照bgsave工作过程有点相似,都是通过fork子进程,由子进程完成相应的操作,同样的在fork子进程简短的时间内,redis是阻塞的。

(1)开始bgrewriteaof,判断当前有没有bgsave命令(RDB持久化)/bgrewriteaof在执行,倘若有,则这些命令执行完成以后在执行。

(2)主进程fork出子进程,在这一个短暂的时间内,redis是阻塞的。

(3)主进程fork完子进程继续接受客户端请求。此时,客户端的写请求不仅仅写入aof_buf缓冲区,还写入aof_rewrite_buf重写缓冲区。一方面是写入aof_buf缓冲区并根据appendfsync策略同步到磁盘,保证原有AOF文件完整和正确。另一方面写入aof_rewrite_buf重写缓冲区,保存fork之后的客户端的写请求,防止新AOF文件生成期间丢失这部分数据。

(4.1)子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。

(4.2)主进程把aof_rewrite_buf中的数据写入到新的AOF文件。

(5.)使用新的AOF文件覆盖旧的AOF文件,标志AOF重写完成。

redis4.0还有一个混合机制;

  • Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。

如果使用 AOF 日志重放,性能则相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动的时候需要花费很长的时间。

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。

混合持久化同样也是通过bgrewriteaof完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将aof_rewrite_buf重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据,如下图:

img

在redis重启的时候,加载 aof 文件进行恢复数据:先加载 rdb 内容再加载剩余的 aof。

混合持久化配置:

aof-use-rdb-preamble yes  # yes:开启,no:关闭

缓存一致性

缓存穿透

  1. 对查询结果为空的情况也进行缓存
  2. 布隆过滤器

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

缓存击穿

redis分布式锁

通过lua脚本去封装逻辑,保证原子性.

先通过setnx命令 expire命令指定过期时间

redis事务

Redis 可以通过 MULTIEXECDISCARDWATCH 等命令来实现事务(transaction)功能。

redis的事务和数据库事务是不一样的,他是没有回滚能力的,所以不满足事务的原子性,持久性其实也是不满足的,所以他的一致性也不满足

使用 MULTI命令后可以输入多个命令。Redis 不会立即执行这些命令,而是将它们放到队列,当调用了EXEC命令将执行所有命令。

这个过程是这样的:

  1. 开始事务(MULTI)。
  2. 命令入队(批量操作 Redis 的命令,先进先出(FIFO)的顺序执行)。
  3. 执行事务(EXEC)。

你也可以通过 DISCARD 命令取消一个事务,它会清空事务队列中保存的所有命令。

WATCH 命令用于监听指定的键,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的键被修改的话,整个事务都不会执行,直接返回失败。

sinterstore 求set集合交集命令
redis消息队列

通过 rpush/lpop 实现队列:

rpush  向 list 的头部(右边)添加元素 lpop 将 list的尾部(最左边)元素取出

通过 rpush/rpop 实现栈:

redis集群

单机

主从复制 无法保证高可用 无法解决写的压力

哨兵模式 无法解决写的压力 主从模式,切换需要时间丢数据

**集群(proxy 型):**代理型, 缺点:增加了新的 proxy,需要维护其高可用。

redis-cluster集群

1、资源隔离性较差,容易出现相互影响的情况。

2、数据通过异步复制,不保证数据的强一致性

redis集群

单机

主从复制 无法保证高可用 无法解决写的压力

哨兵模式 无法解决写的压力 主从模式,切换需要时间丢数据

**集群(proxy 型):**代理型, 缺点:增加了新的 proxy,需要维护其高可用。

redis-cluster集群

1、资源隔离性较差,容易出现相互影响的情况。

2、数据通过异步复制,不保证数据的强一致性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值