面试老问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个元素删除
3.1.3 UNLINK (4.0版本以后)
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)如下:
|
|
一旦节点 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的计算规则将键映射到对应的槽上