[TOC]
关键字
单线程,epoll,cluster,sentinel,gossip,raft,
分布式锁,穿透,击穿,雪崩,数据一致性,
sds,ziplist,skiplist,rehash,hyperloglog,
热key,大key,过期清理,淘汰策略,主从复制,rdb,aof,aof rewrite
string,hash,set,zset的底层数据结构实现,hash的渐进式扩容
hyperloglog标准误差多少,原理是啥
再加上 6.0之后的加入的多线程 工作机制
缓存过期重置。锁刷新
一致性哈希算法
分布式锁
setnx讲起,最后慢慢引出set命令的可以加参数,
setnx 是SET if Not eXists(如果不存在,则 SET)的简写。万一set value 成功 set time失败
setex是一个原子性(atomic)操作,关联值和设置生存时间两个动作会在同一时间内完成。
redisson的锁,就实现了可重入,他使用了LUA的Hash数据结构。
cluster
Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能。
自动将数据进行分片,每个 master 上放一部分slot数据 提供内置的高可用支持,部分 master 不可用时,还是可以继续工作的 维护数据采用的是gossip协议
节点发现原理:
发送CLUSTER MEET命令握手,meet-pong-ping 握手完成
节点A会将节点B的信息通过Gossip协议传播给集群中的其他节点,让其他节点也与节点B进行握手,
最终,经过一段时间之后,节点B会被集群中的所有节点认识。
gossip 协议,Gossip协议由MEET、PING、PONG,FAIL种消息实现
每次发送MEET、PING、PONG消息时,发送者都从自己的已知节点列表中随机选出几个节点(可以是主节点或者从节点),并将这两个被选中节点的信息分别保存到两个clusterMsgDataGossip结构里面。
所有节点都持有一份元数据,不同的节点如果出现了元数据的变更,就不断将元数据发送给其它的节点,让其它节点也进行元数据的变更。
gossip有一定延迟,因为节点是逐步传播的
Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽(slot)
数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。
当每个slot 都有节点处理的时候,集群才算上线;CRC16(key),MOVED错误重定向到正确节点
跳跃表来保存槽和键之间的关系
主从复制:主节点用于处理槽,而从节点则用于复制某个主节点,替补上线;
(复制:slaveof命令,发送地址-socket连接-ping-pong-replconf-psync)
原理:master负责写,异步同步slave;,从服务器将向主服务器发送PSYNC命令,执行同步操作,
PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partialresynchronization)两种模式:
开启后台线程生成RDB,同时将从客户端收到的所有写命令缓存在内存(内存缓冲区),
RDB完成后 master发送给slave,slave写入本地磁盘,再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。
故障转移: 检测:定期发送ping检测在线,没有在规定时间返回pong消息,标记为pfail,超过半数节点标记,标记fail 转移:选择从节点,选举主节点,转移slot,集群广播自己为主节点 选举:选举新主节点和Sentinel的方法非常相似,两者都是基于Raft算法
哨兵
Redis的高可用性(high availability)解决方案 监视主从节点,执行故障转移
原理: 大部分的哨兵都同意才能判断下线,开始raft选举master 哨兵作用是监控、通知、故障转移 info 获取主从信息 发布订阅功能获取其他哨兵节点的信息 通过向其他节点发送 ping 命令进行心跳检测,判断是否下线。 Raft 算法选举负责故障转移的哨兵,从节点替换,slaveOf通知更新
问题: 主备切换数据丢失:一种是异步复制,一种是脑裂导致的数据丢失
单线程
执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程的。
Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器。
因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
文件事件处理器以单线程方式运行,但通过使用I/O多路复用程序来监听多个套接字,
文件事件处理器既实现了高性能的网络通信模型,又可以很好地与Redis服务器中其他同样以单线程方式运行的模块进行对接,这保持了Redis内部单线程设计的简单性
IO多路复用:I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流)
内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。
epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间
epoll:
epoll内部使用了mmap共享了用户和内核的部分空间,避免了数据的来回拷贝;
epoll基于事件驱动,避免了像select和poll对事件的整个轮询操作
hyperloglog标准误差多少,原理是啥
如果允许统计在巨量数据面前的误差率在可接受的范围内,
1000万浏览量允许最终统计出少了一两万这样子,可采用HyperLogLog算法来解决上面的计数类似问题
计数存在一定的误差,误差率整体较低。标准误差为 0.81% 。
能够使用极少的内存来统计巨量的数据,只需要12K内存就能统计2^64个数据。
原理: 抛硬币的伯努利实验:无论抛了多少次,只要出现了正面,就记录为一次试验,推导出n和k_max中存在估算关联:n = 2^(k_max)
HyperLogLog是这样做的。对于输入的数据:
通过hash函数,将数据转为比特串,根据存入数据中,转化后的出现了 1 的最大的位置 k_max 来估算存入了多少数据。
分桶就是分多少轮。抽象到计算机存储为单位是比特(bit),长度为 L 的大数组 S ,
将 S 平均分为 m 组,然后每组所占有的比特个数是平均的,设为 P
在 Redis 中,HyperLogLog设置为:m=16834,p=6,L=16834 * 6。占用内存为=16834 * 6 / 8 / 1024 = 12K) 对应:代入指定的估算公式中即可