Please enable Javascript to view the contents

Redis

 ·  ☕ 5 分钟

面试老问redis,害的我又看了看部分源码

1、版本主要特性

最初的版本只有三种数据结构string,list,set

后来 增加了 zset

最后加的hash

2.4左右增加了swap交换内存,然后性能有问题,2.6又干掉了

3.0增加的集群

4.0增加了module

5.0增加了stream

6.0增加了多线程

删除之前用的del,现在用的ulink

2、过期策略 和淘汰机制

为啥过期是策略,淘汰是机制?那是因为策略是概述,机制是具体的执行。策略先行,机制后补。

过期策略 就是 定时扫描抽样删除 和 惰性删除。
定时扫描是一种主动策略,但是redis里边如果key过多,每次全部扫描肯定会浪费大量的cpu资源,
所以每次只能抽样检测。
so,问题来了,抽样检测肯定是不全面的,会漏掉过期的key,那怎么办呢?
被动删除,也就是他们说的惰性删除,也就是说,你查询一个key的时候,会判断过期时间,如果过期那么就会删除,
不返回给你任何东西。

被动删除也有了,但是还是有问题,如果我是一直添加,而没有查询,那么被动删除是没法起作用的。
那么就会导致大量的key堆积到内存里边,为了能够继续添加新key,那么就要执行淘汰机制,确保新的key可以顺利
添加。所以,淘汰机制首先是不淘汰,抛出添加异常,不让你添加任何key,然后是柿子找软的捏,找带过期时间的
执行lru,lfu,随机,ttl,如果都没过期时间咋办?全局执行lru,lfu,随机。

3、redis的大key

3.1、大key的删除

3.1.2 渐进式删除

分批删除,通过 scan 命令遍历大key,每次取得少部分元素,对其删除,然后再获取和删除下一批元素。

3.1.2.1 key改名(逻辑上删除)

3.1.2.2 每次取出100个元素删除

UNLINK 工作思路:

(1)在所有命名空间中把 key 删掉,立即返回,不阻塞。

(2)后台线程执行真正的释放空间的操作。

UNLINK 基本可以替代 del,但个别场景还是需要 del 的,例如在空间占用积累速度特别快的时候就不适合使用UNLINK,因为 UNLINK 不是立即释放空间。

3.2、大key的监控

3.2.1、redis-rdb-tools工具。

redis实例上执行bgsave,然后对dump出来的rdb文件进行分析,找到其中的大KEY。

3.2.2、redis-cli –bigkeys命令。

可以找到某个实例5种数据类型(String、hash、list、set、zset)的最大key。

3、自定义的扫描脚本

以Python脚本居多,方法与redis-cli –bigkeys类似。

4、debug object key命令。

可以查看某个key序列化后的长度,每次只能查找单个key的信息。官方不推荐。

3.3、大key的其他问题

4、redis扩容保持一致性

扩容操作可分为如下步骤:

4.1、准备新节点。

4.2、加入集群。

4.3、迁移槽和数据。

4.3.1 Redis Cluster 重定向问题 - Moved/Ask重定向

Ask重定向发生于集群伸缩时,集群伸缩会导致槽迁移,当我们去源节点访问时,此时数据已经可能已经迁移到了目标节点,使用Ask重定向来解决此种情况。

moved错误代表槽的负责权已经从一个节点转移到了另一个节点:在客户端收到关于槽i的moved错误之后,客户端每次遇到关于槽命令的时候,都直接将命令请求发送至moved错误所指向的节点,因为该节点就是负责 i槽的节点
与此相反,ask错误只是两个节点在迁移槽的过程中使用的一种临时措施:在客户端收到关于槽i的ask错误之后,客户端只会在接下来的一次命令请求中将关于槽i的命令请求发送至ask指定的节点,但是这种转向不会对客户端今后发送关于槽i的命令请求产生任何的影响,客户端仍然会将关于槽i的命令请求发送至目前处理槽i的节点,除非ask错误再次出现。

moved和ask重定向错误的区别在于,moved重定向错误是在迁移完成之后,ask重定向错误是在迁移过程中发生的。

MOVED 转向与 ASK 转向的区别类似于 http 协议中 301 跳转与 302 跳转的区别

对于客户端来说,同一个key的moved只会出现一次,下次就会直接请求moved对应的ip和端口
而ask是一种不稳定状态,下次还的问

当一个槽被设置为 MIGRATING 状态时, 原来持有这个槽的节点仍然会继续接受关于这个槽的命令请求, 但只有命令所处理的键仍然存在于节点时, 节点才会处理这个命令请求。

如果命令所使用的键不存在与该节点, 那么节点将向客户端返回一个 -ASK 转向(redirection)错误, 告知客户端, 要将命令请求发送到槽的迁移目标节点。

当一个槽被设置为 IMPORTING 状态时, 节点仅在接收到 ASKING 命令之后, 才会接受关于这个槽的命令请求。

如果客户端没有向节点发送 ASKING 命令, 那么节点会使用 -MOVED 转向错误将命令请求转向至真正负责处理这个槽的节点。

从客户端的角度来看, ASK 转向的完整语义(semantics)如下:

1
2
3
4
5
6
如果客户端接收到 ASK 转向, 那么将命令请求的发送对象调整为转向所指定的节点。

先发送一个 ASKING 命令,然后再发送真正的命令请求。

不必更新客户端所记录的槽 至节点的映射: 槽 应该仍然映射到节点 A , 而不是节点 B 。

一旦节点 A 针对槽 的迁移工作完成, 节点 A 在再次收到针对槽的命令请求时, 就会向客户端返回 MOVED 转向, 将关于槽 的命令请求长期地转向到节点 B 。

注意, 即使客户端出现 Bug , 过早地将槽 映射到了节点 B 上面, 但只要这个客户端不发送 ASKING 命令, 客户端发送命令请求的时候就会遇上 MOVED 错误, 并将它转向回节点 A 。

5、监控指标

5.1、性能指标:Performance

5.2、内存指标: Memory

5.3、基本活动指标:Basic activity

5.4、持久性指标: Persistence

5.5、错误指标:Error

6、其他

k值采用CRC16(k)&16383的计算规则将键映射到对应的槽上