redis设计与实现

本文深入探讨了Redis的本质,揭示了为何使用远程缓存服务器而非本地Map。Redis提供了5种标准缓存数据结构,具备持久化、排序、并集操作等功能,支持原子操作和分布式数据分片。此外,文章还介绍了Redis与MySQL的区别,以及Redis的单机数据库功能、主从复制、哨兵模式和集群环境下的高可用性策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis的本质

1.一台远程服务器,通过sokect连接客户端,并向客户端提供缓存服务(提供了5种标准的缓存数据结构)
2.为什么客户端不在本地用Map缓存数据,而需要一台独立的服务器做缓存?
1)因为分布式和集群概念兴起,一个应用,需要多台服务器协同工作,多台服务器意味着多个JVM
2)多个JVM意味着跨JVM,跨JVM意味着我们要如何保证不同JVM的本地缓存数据保持最终一致性?
3)为了绕开这个问题,redis另起炉灶做了个客户端共用的缓存服务器,并向多个客户端提供缓存服务
4)缓存服务器就类似一个远程的共享内存块,多个客户端向服务器发送读写命令,都是读写同一个内存块的数据
3.redis缓存比本地缓存(Map)的优势
1)redis对外定义了5种标准的缓存数据结构,而虽edis的key只支持string,但value支持string,list,set,zset,hash
2)redis作为一个完整的缓存中间件,实现了很多实用的功能,而这些功能Map都是不具备的,若要具备,需要Map独立实现
3)例如持久化,zset排序功能,set并差集操作,string的自增功能,一些统计功能,以及一些缓存失效策略
4)读写命令操作都是原子操作,不需要像HashMap一样手动保证线程安全
5)支持分布式的数据分片功能,高可用的主从配置以及数据备份功能
4.redis和mysql的区别
1)redis追求性能的最大化,牺牲了一定的持久性、一致性,mysql追求数据的持久性、一致性,也牺牲了一定的性能
2)两者架构有些类似,也有不同,但是数据存放的架构模式类似:内存+磁盘
3)redis内存:内存存放的主要是热点数据,数据纯内存操作,即使单线程处理,运行速度也很快
4)mysql内存:内存使用上为了保持数据一致性和持久性,需要容忍磁盘慢IO同步,牺牲了部分性能追求
5)redis磁盘:redis的内存是按(key,value)结构组织的,有两种磁盘文件:RDB(复制内存数据的方式)和AOF(追加命令的方式)
6)mysql磁盘:mysql的行数据是按一定表结构组织的,所以数据的持久化是按一定结构进行整理保存的,并保证Commit的数据不会丢失

redis对外5种标准数据结构的实现

1.对外标准数据结构的定义
1)对外标准数据结构是指客户端能感知到的数据结构类型(string,list,set,zset,hash)
2)实际上,redis为了高效利用有限的内存和cpu,在5大数据结构对象之下,设计了6种基础数据结构
3)6种基础数据结构:简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表
简单动态字符串:修改时是在原有char[]数组修改,自动扩展分配内存,杜绝内存溢出,二进制安全
链表:C语言无链表实现,redis自己实现,redis链表是双向链表
字典:C语言无字典实现,redis自己实现,redis字典有多态属性,不同键值对有不同的实现函数、渐进式rehash
跳跃表:性能和平衡树相媲美在zset和集群节点上有应用,结构:头指针,尾指针,最大层级,节点数量
整数集合:intset集合-有序无重复元素,元素整数会根据位数大小自动升级,类型自适应的方式避免了类型出错以及节约内存
压缩列表:zipList应用于节点较少,节点值可以是小整数或者短字符串,包括哈希集合也可应用,主要是为了节约内存
4)上述redis设计出了很巧妙的6种基本数据结构类型,但是服务器接口并不是直接操作这些基本类型的数据结构
5)而是在6种基础数据结构之上,构建了5大对象系统(string,list,set,zset,hash),不同对象针对相同的命令做出多态反应
6)对象运行时会根据不同的数据状态择出最优的基本数据结构类型实现,并实现了引用计数的gc机制以及引用内存对象共享机制
7)gc机制通过对象属性refCount实现,内存共享对象只支持1-9999整数,对象属性还会记录最后一次被访问时间
8)redisObject对象结构:type=string,list,set,zset,hash;encoding=6种基本数据结构类型;ptr=指向底层数据结构的指针
string对象:encoding类型:<39位=int、long、embst、>39位=raw、,raw需分配两次内存,embst是固定内存位数只读的
list对象:encoding类型:zipList、linkedList,zipList单个元素值必须小于64字节,元素个数小于512个,否则自动转换
hash对象:encoding类型:zipList、hashTable,每个键值对组成一个元素压进zipList,同时也会自动转换
set对象:encoding类型:intSet、hashTable,intSet集合都是整数值并且元素个数小于512个,否则自动转换
zset对象:encoding类型:zipList、skipList,zipList结点元素和分值,同时满足单个元素值小于64字节,元素个数小于128个
2.单机数据库基本功能
1)服务器对象redisServer,保存了redisDb数组【】,长度16,默认使用db【0】
2)数据库对象redisDb,保存了一个键值对空间字典,服务器可以对键空间执行很多操作命令
3)服务器可以对键expire-秒或pexpire毫秒设置过期时间,redisDb还保存了键-过期时间字典
4)过期删除策略:定时删除(密集触发占用cpu)、惰性删除(不再访问内存泄漏)、定期删除(定时任务删除)
5)redis持久化策略有rdb和aof,rdb已过期的键不会重新载入服务器,aof则不会考虑键是否过期场景
6)redis2.8版本新增了数据库通知功能和键通知功能,通知即是订阅给定的频道或者模式,监控其命令状态
7)rdb文件是通过save(阻塞)和bgsave(异步子进程)实现,serverCron每隔100秒检查是否满足条件执行bgsave
8)aof文件包含三步:aof缓存命令追加、文件写入、文件同步,文件同步有三种策略,每条同步、每秒同步、操作系统决定
9)aof恢复(伪造客户端发送文件命令),aof重写(压缩文件大小),重写复制子进程,父进程追加命令到父子进程aof缓存
10)redis文件事件:与客户端每个交互动作会有一个文件事件处理器来处理和做出相应动作响应客户端
3.多机协同提供服务
1)主从服务:从slaveOf主,2.8版本前断线重连低效(重同步低效),同步复制功能包含两步:同步和命令传播
2)从请求sync到主,主起子进程发rdb文件到从,并且发命令缓存到从服务器,至此复制成功
3)旧版本低效:重连复制同步阶段需完全同步;新版本高效:重连复制同步阶段部分同步,部分同步关键在于主从维护复制偏移量
4)主会维护复制积压缓冲区,缓冲区会记录最近传播命令,重连从会报告当前psync偏移量,主根据偏移量同步需要传播命令
5)主从同步下的哨兵模式:redis服务器已哨兵模式启动,维护了一个主服务器实例的字典(键:实例名称,值:实例元信息)
6)主服务器实例会记录实例机器的基本信息,实例id,从服务器,下线标记状态,故障迁移状态的最大时限
7)哨兵服务器会在主服务创建两个连接,命令连接,订阅连接,哨兵集群之间发现是通过主服务器订阅频道来感知
8)故障转移下线判断时,哨兵之间会通过命令连接交换主服务器下线状态,使主服务器从主观下线变成客观下线
9)故障转移前需要选出领头哨兵执行故障转移,选举数据完整度高,最近网络通信好的从服务器为主服务器
4.集群环境下的高可用
1)redis集群构造了节点(机器,redis只能使用0号db库),槽指派,命令执行,重新分片、转向、故障转移、消息等概念
2)服务器初始化时判断以集群模式启动之后,会成为自己集群的第一个节点,手动执行cluster meet命令能吞并其他节点集群
3)集群下每个节点记录了节点的元信息(clusteNode),元信息包含当前节点视角下集群配置信息(clusterLink)
4)集群在槽指派完成之前不能提供服务,槽一共16384(0…16383),每个节点会记录下自己分配到的槽(二进制数组标识)
5)集群下,还需记录下其他槽分配到的指定节点,以便集群执行命令的时候可以重定向到其他节点(move指令到客户端)
6)集群下的槽可以转移其他节点,但是会发生ASK错误,槽转移时,槽存在的键有可能被访问,命中不了需要到转移节点访问
7)集群下clusterStatus下的重要字段:myself(clusterNode),槽-节点数组,槽键跳跃表,其他节点要导入的槽的标记
8)集群下节点分为主和从节点,redis命令可指定一个节点成为另一个节点的从,节点之间通过ping检测集群其他节点是否下线
9)主节点检测到其他主节点疑似下线时会广播到集群节点,当有半数主节点认为该节点疑似下线,则标记为正式下线
10)执行故障转移时,主节点具有投票权,下线节点的从节点具有竞选权,从节点知道自己主节点下线时,就会参与竞选
竞选过程:从节点向所有主节点要求自己变成主节点,投票主节点发现自己一次投票权还在,就会投票支持该从节点
竞选过程:从节点收集到超过半数的投票数,即竞选成功,从选举拉票具有先来先到的特点,故障转移完成会广播到集群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值