redis 设计与实现

Redis设计与实现
前言
redis版本说明
数据结构与对象
简单动态字符串
SDS
可以修改
区别于C语言字符串
三个属性
free:值为0表示未分配使用空间
len :属性值为5表示SDS保存了五字节长的字符床
buf:属性是char类型的数组
SDS与C字符串的区别
SDS
常数复杂度获取SDS长度
len 属性 确保获取长度不成为性能瓶颈
C语言
需要遍历字符串长度
杜绝缓冲区溢出
扩容之前判断len是否满足扩容
减少修改字符串带来的内存重新分配次数
空间预分配
预先分配free 空间

                SDS的长度大于等于1M,free大小将分配1M
                SDS长度小于1M,free大小预分配len属性大小同样长度
            惰性空间释放
                删除字符串之后,将删除空间分配到free属性中
        二进制安全
            C语言使用空串作为结尾
            SDS可以保存二进制文件,不会丢失包含空串数据
        兼容部分C字符串
    链表
        特点
            特点
                高效重排能力
                顺序节点访问
                redis 自己构建了链表实现(C语言没有链表)
            链表和链表节点的实现
                listNode (双端链表)实现
                特点
                    双端
                    无环
                    带有表头指针,表尾指针
                    持有长度计数器
                    多态(可以保存多种数据类型)
    字典
        特点
            C语言未内置字典数据结构
            redis自己实现字典
            字典是hash键的底层实现之一
        字典的实现
            hash表
                table
                size
                used
                sizemask
                    决定新增数据应该放到数组哪个索引上面
            hash表节点
                dictEntry
                union{}
                next
            hash算法
                计算hash值
                根据hash值计算index
            解决键冲突
                hash表出现同一个数据在同一个索引上
                新加入数据总在表头位置
            rehash
                扩展和收缩通过rehash(重新散列实现)
                创建新的表
                    根据旧表hash计算索引和新表的值
                        复制旧表数据到新表
                            释放旧表
            渐进式rehash
                rehash动作不是一次完成的6
                    数据量巨大的时候
                        分多次
                        渐进式rehash
                    分而治之的思想,庞大的计算量平均到每一次hash计算
                具体步骤
                    分配新表(字典同时持有旧表和新表)
                        rehashindex变量==0 rehash正式开始
                            rehash期间,除去对数据增删查操作外,旧表数据同时rehash到新表上
                        旧表不再新增数据,全部新增到新表上
    跳跃表
        特点
            有序的数据结构
            平均时间复杂度O(logn),最坏O(N)
            效率媲美平衡树,实现更加简单
            跳跃表使用的地方:有序集合&集群节点内部数据结构使用跳跃表
            跳跃表最高32层
            跳跃表数据结构
                zskipList
                zskipListNode
                    head
                    tail 
                    len
            同一个跳跃表多个节点包含相同的分值,每个节点的成员对象必须是唯一的
            跳跃表中的节点按照分值大小进行排序,分值大小相同的时候,按照成员大小进行排序
    整数集合
        特点
            集合键的底层实现之一
            升级过程不可逆
    压缩列表
        特点
            列表键和hash键的底层实现之一
            redis为了节约内存开发出压缩列表
                包含任意多个节点
    对象
        对象类型与编码
            类型
                字符串对象
                列表对象
                    zset 同时使用跳跃表和字典实现
                        跳跃表范围查询快,根据key寻找value慢
                        字典表范围查找慢,需要额外空间进行数据排序 ,查询慢
                hash对象
                集合对象
                有序集合对象
        内存回收
            C语言不具有自动内存回收功能,redis在自己内存系统构建一套回收机制
            对象引用计数信息
                创建对象时 引用计数初始化为1
                新程序使用时,引用计数值增加1
                不被一个程序使用时间,引用计数值-1
                引用计数归0时间,对象占用内存会被释放
        对象共享
            共享步骤
                将键指针指向已经存在的对象
                将共享的对象的引用计数+1
            对象的空转时长
                当前时间-lru时长
    重点
        redis数据库中的每个键值对的key和value 都是对象
        对象类型
            字符串
            列表
            hash
            集合
            有序集合
            每种集合最少包含两种编码方式,不同的编码方式可以在不同的场景优化对象的使用效率
                具体编码方式和区别
                     todo
            redis对应系统带有引用计数实现的内存回收机制,对象不再使用 ,自动回收
            redis会共享0-9999的字符串对象
            对象会记录最后一次的访问时间,这个时间用于计算对象的空转时间
单机数据库实现
    数据库
        服务器中的数据库
            服务器dbnum决定6Redis服务器初始化数据库数量,默认数据库16个
        切换数据库
            客户端无法显示目标数据库号码,执行flushDb等命令的时候,最好先执行一下select 显式切换到指定数据库
        数据库键空间
            添加新键
            删除键
            更新键
            对键取值
            其他键空间操作
                flushdb
                dbSize
                exists
                keys
            读写键空间时的维护操作
                更新命中次数
                更新LRU时间
                读取键数据时发现键数据已经过期,优先删除过期数据
                使用watch命令监视某个键,服务器会对被监视的数据标记为dirty ,从而让事物程序注意到某个键已经修改过
                服务器修改数据之后,会对相应的数据标记dirty,该键计数器值增加1
                服务器开启通知,对数据修改之后,服务器按照配置发送相应数据到数据库
        设置键生存时间或者过期时间
            tips
                setnx: 只能用于字符串
            设置过期时间
            保存过期时间
            移除过期时间
                PERSIST:移除过期时间
            计算并返回剩余生存时间
                TTL:秒级别返回剩余生存时间
                PTTL:毫秒级别返回过期时间
            过期键的判定
                过期字典查询
                TTL命令
        过期删除策略
            定时删除
            惰性删除
             定期删除
        redis的过期删除策略
            惰性删除的实现
            定期删除策略的实现
        AOF|RDB和复制功能对过期键的处理
            生成RDB文件
            载入RDB文件
            AOF写入
            复制
        数据库通知
            redis 2.8增加通知功能
                根据通知显示,三条命令对message进行操作 
                    set
                    expire
                    del
            发送通知
            发送通知的实现
        重点回顾
            redis服务器的所有数据库都保存在redisServer..db数组中,数据库数量保存在redisserver.dbnum中
    RDB持久化
        特点
            redis是键值对数据库服务器
            RDB持久化可以手动执行,也可以根据服务器配置定期执行
            RDB文件持久化的是经过压缩的二进制文件
            具体持久化命令
                SAVE()
                BGSAVE()
        RDB文件的创建与载入
            两条命令
                SAVE()
                    阻塞redis进程,服务器不能处理任何命令请求
                BGSAVE()
                    创建子进程,子进程创建RDB文件,服务器进程继续处理命令请求
            RDB文件只有在启动服务器的时候自动执行,没有专门执行RD9B文件的命令
            AOF文件更新频率更高
                开启AOF文件持久化,服务器优先使用AOF模式还原数据
            save命令执行时服务器的状态
                阻塞
            BGSAVE命令执行时服务器状态
                阻塞
            RDB文件载入的时候服务器状态
                阻塞
        自动保存时间间隔
        设置保存条件
        检查保存条件是否满足
        RDB文件结构
            分支主题
    AOF持久化
        特点
            AOF:保存的命令
            RDB:保存的是具体键值对
        AOF持久化的实现
            命令追加
            AOF文件的写入和同步
            AOF文件的载入和还原
            AOF重写
            AOF重写功能实现
                旧AOF文件包含所有键值对命令
                重写完成的AOF文件吗,包含能恢复当前数据库状态的数据命令
            AOF后台重写
                创建子进程进行重写AOF文件操作
                避免锁的情况下保证数据安全
                    设置AOF文件缓冲区
                    子进程重写AOF文件期间服务器主进程
                        1、执行客户端命令
                        2、执行后的命令追加到旧AOF文件
                        3、执行后的命令追加到AOF重写缓冲区
                子进程完成工作后,发送信号到父进程,父进程调用函数
                    1、重写内容替换到缓冲区AOF文件
                    2、新AOF文件和旧AOF文件的替换
                    只有调用函数的部分线程会阻塞
    事件
        特点
            redis 是事件驱动程序
                文件事件
                    套接字进行链接
                    文件事件是对套接字操作的抽象
                    服务器通过监听并处理这些事件
                    实现机制
                        网络事件处理器:文件处理器
                            使用IO多路复用IO,同时监听多个套接字
                                被监听的套接字执行链接
                                    accept
                                    read
                                    write
                                    close
                                高性能网络通信模型
                    文件事件处理器的构成
                        构成
                            套接字:套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面
                            IO多路复用
                                监听套接字
                                传送套接字
                            文件事件分派器
                                产生事件的套接字放到一个队列里面,队列有序,同步的向事件分派器发送套接字
                            事件处理器
                    IO多路复用IO的实现
                        包装常用的select、epoll、evport和kqueue等IO复用函数库实现
                        redis为每个IO多路复用IDO复用函数都实现了相同的API,所以IO多路复用IO的程序的底层是可以互换的
                        编译时总会选择性能最高的IO复用函数作为复用程序的实现
                    事件类型
                        可读操作,调用AE_readable
                        可写操作,调用AE_writeable
                        同时发生,写操作在读操作之后
                    API
                    文件事件处理器
                        链接应答处理器
                        命令请求处理器
                        命令回复处理器
                时间事件
                    redis服务器在给定的时间点执行
                    特点
                        定时事件
                        周期性事件
                        时间事件属性
                            id:全局唯一
                            when:
                            timeProc:事件事件处理器:调用响应处理器处理事件 
                    实现
                        所有的时间事件都放在一个无序链表中,每当事件事件执行的时候,遍历整个链表处理事件
                    时间事件应用实例:“serverCorn函数
                        更新服务器统计信息
                        清理数据库过期键值对
                        关闭清理过期失效客户端
                        尝试进行AOF|RDB持久化操作
                        主服务器:同步从库文件
                        集群模式:定期同步和链接测试
                事件的调度与执行
    客户端
        特点
            分支主题
    服务器
        命令请求的执行过程
            发送命令请求
            读取命令请求
            命令执行器:
                查找命令实现
                执行预备操作
                调用命令实现函数
                执行后续工作
                命令回复发送客户端
                客户端接收打印命令回复
        serveCorn函数
        更新服务器时间缓存
            更新LRU时钟
多机数据库实现
    复制
        旧版复制功能的实现
            命令传播
                同步数据库修改状态同步
                分支主题
            同步
                数据库状态的更新到主服务器状态
                1、发送sync命令
                2、执行bgsave命令,生成RDB文件,使用缓冲区执行所有命令
                3、同步到从服务器
        新版复制功能实现
            分支主题
    sentinel
    集群
独立功能实现
    发布与订阅
    事物
    lua脚本
    排序
    二进制位数组
    慢日志查询
    监视器
resp协议
    RESP 协议有如下几个特点:
        实现简单;
        快速解析;
        可阅读;
    RESP 是基于 TCP 协议实现的
        可以使用socket链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大涛小先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值