阿里资深专家整理的Redis5设计与源码分析宝典终于横空出世

学习本文之前先问大家一个问题,为什么要学习redis?不知道如何回答的朋友,请继续往下看!

总共总结为三点的内容,大家仔细斟酌一下:

1.Redis应用广泛,它有卓越的性能、丰富的数据类型,简洁高效的设计理念。

2.Redis 5带来了很多不错的新特性:

  • 增加了新的流数据类型

  • 更新了定时器、集群和字典相关的API

  • 增加了新的有序集合命令

3.要想做好日常开发和运维工作,需要对Redis的底层原理和实现,尤其是命令实现有一定了解。

Redis已经是IT企业技术栈中重要的一环,与其相关的从业者数量也逐年增多,对大多数人来说Redis可谓既熟悉又神秘,只有不足4MB的源码却实现了一个功能丰富且健壮的数据库。

Redis 以其高速、轻量和丰富的数据结构与功能被越来越多的工程师所钟爱。然而,用Redis 的人很多,真正懂Redis的人很少,本文正是写给那些使用了Redis并希望进一步深入理解Redis的读者。作者及其团队通过对Redis最新版本(5.x)各部分源码的分析,庖丁解牛,深入浅出,带领读者一步步探索Redis的方方面面,让读者从原理层面真正懂得Redis。

本文不仅深入源码讲解了Redis.常用的底层数据结构和常用命令处理的实际过程,还细致入微地讲述了基数计数算法的演进和HyperLogLog算法在Redis 中的具体实现,这是非常有用且难得的;

本文从源码层面对Redis进行深入剖析,尤其是数据结构部分,其学习意义不限于Redis,强烈推荐大家来阅读。

限于文章篇幅原因,只能以截图的形式展示出来,有需要的小伙伴可以文末获取↓↓↓

目录概览

内容概览

本文将用22章的内容给大家展开讲解Redis5设计、数据结构、底层命令实现,以及持久化、主从复制、集群的实现;

第1章 引言

Redis是目前最流行的键值对( key-value)数据库,以出色的性能著称,官方提供的数据是可以支持100 000以上的+QPS。Redis具有高性能的主要原因如下。

  1. Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快。
  2. Redis是单进程线程的服务(实际上一个正在运行的Redis Server肯定不止一个线程,但只有一个线程来处理网络请求),避免了不必要的上下文切换,同时不存在加锁/释放锁等同步操作。
  3. Redis使用多路I/O复用模型(select、poll、epoll),可以高效处理大量并发连接。
  4. Redis中的数据结构是专门设计的,增、删、改、查等操作相对简单。

本章主要介绍Redis简介、Redis 5.0的新特性、Redis源代码概念、Redis安装与调试,希望对读者阅读和研究Redis 源码有一定的帮助。

第2章 简单动态字符串

简单动态字符串(Simple Dynamic Strings,SDS)是Redis的基本数据结构之一,用于存储字符串和整型数据。SDS兼容C语言标准字符串处理函数,且在此基础上保证了二进制安全。本章将详细讲解SDS的实现,为读者理解Redis的原理和各种命令的实现打下基础。

第3章 跳跃表

有序集合在生活中较常见,如根据成绩对学生进行排名、根据得分对游戏玩家进行排名等。对于有序集合的底层实现,我们可以使用数组、链表、平衡树等结构。数组不便于元素的插入和删除;链表的查询效率低,需要遍历所有元素;平衡树或者红黑树等结构虽然效率高但实现复杂。Redis采用了一种新型的数据结构—―跳跃表。跳跃表的效率堪比红黑树,然而其实现却远比红黑树简单。

第4章 压缩列表

压缩列表ziplist本质上就是一个字节数组,是Redis为了节约内存而设计的一种线性数据结构,可以包含多个元素,每个元素可以是一个字节数组或一个整数。

Redis 的有序集合、散列和列表都直接或者间接使用了压缩列表。当有序集合或散列表的元素个数比较少,且元素都是短字符串时,Redis便使用压缩列表作为其底层数据存储结构。列表使用快速链表( quicklist)数据结构存储,而快速链表就是双向链表与压缩列表的组合。

例如,使用如下命令创建一个散列键并查看其编码。

127.0.0.1:6379> hmset person name zhangsan gender 1 age 22   
OK
127.0.0.1:6379> object encoding person
" ziplist"

本章将从源码层次详细介绍压缩列表的存储结构及基本操作。

第5章 字典

本章讲解了字典的基本概念,并对其实现进行深入解读,字典在Redis数据库中起到了举足轻重的作用,想必读者读完这章之后,对字典的概念及Redis数据库底层是如何存储数据都会有一个较为清晰的了解。请思考,在5.2.1节中介绍字典的基本实现中为什么Hash表数组中存放的是每个dictEntry 的指针地址,而不是直接把dictEntry嵌入到Hash表数组中去?

第6章 整数集合

整数集合(intset)是一个有序的、存储整型数据的结构。我们知道Redis是一个内存数据库,所以必须考虑如何能够高效地利用内存。当Redis集合类型的元素都是整数并且都处在64位有符号整数范围之内时,使用该结构体存储。

第7章 quicklist的实现

quicklist是Redis底层最重要的数据结构之一,它是Redis对外提供的6种基本数据结构中List的底层实现,在Redis 3.2版本中引入。在引入quicklist之前,Redis采用压缩链表(ziplist)以及双向链表( adlist)作为List的底层实现。

当元素个数比较少并且元素长度比较小时,Redis采用ziplist作为其底层存储;当任意一个条件不满足时,Redis采用adlist作为底层存储结构。这么做的主要原因是,当元素长度较小时,采用ziplist可以有效节省存储空间,但ziplist的存储空间是连续的,当元素个数比较多时,修改元素时,必须重新分配存储空间,这无疑会影响Redis的执行效率,故而采用一般的双向链表。

quicklist是综合考虑了时间效率与空间效率引入的新型数据结构,本章将对其具体实现细节为读者——展现。

第8章 Stream

消息队列是分布式系统中不可缺少的组件之一,主要有异步处理、应用解耦、限流削峰的功能。目前应用较为广泛的消息队列有RabbitMQ、RocketMQ、Kafka等。Redis在最新的5.0.0版本中也加入了消息队列的功能,这就是Stream。本章将详细介绍Redis Stream相关的底层数据结构,帮助读者探索Stream实现的秘密。

第9章 命令处理生命周期

第2~8章介绍了Redis 的基本数据结构,接下来主要讲解所有命令的源码实现。在讲解命令实现之前,需要先了解一下服务器处理客户端命令请求的整个流程,包括服务器启动监听,接收命令请求并解析,执行命令请求,返回命令回复等,这也是本章的主题“命令处理的生命周期”。

Redis服务器是典型的事件驱动程序,因此事件处理显得尤为重要,而Redis将事件分为两大类:文件事件与时间事件。文件事件即socket的读写事件,时间事件用于处理一些需要周期性执行的定时任务,本章将对这两种事件作详细介绍。

第10章 键相关命令的实现

在前面的章节里,我们主要讲了Redis常用的底层数据结构以及命令处理的生命周期,本章将介绍键相关命令的源码实现。命令实现的过程中不是直接操作这些数据结构,我们将在10.1节讲解这两个结构。

在理解了redisDb和redisObject对象之后,我们按照查看键信息、设置键信息、查找和操作键将本章命令进行分类讲解,10.2节讲解查看键信息相关命令,其中 object和 type命令是获取redisObject对象相关属性的操作,过期时间读取和修改相关命令是对redisDb的expires字典的操作,除此之外本章的命令都是对redisDb的dict字典的操作。

第11章 字符串相关命令的实现

字符串命令是Redis最常见的命令,相对其他命令来说,字符串命令操作简单,参数较少。字符串命令虽然简单但作用强大,我们可以用字符串命令实现key-value的设置与获取,也可以实现计数器功能,甚至可以实现位操作。

第12章 散列表相关命令的实现

散列表是Redis数据组织的基本结构。针对key-value中的value,Redis提供了6种结构——字符串(string)、散列表(Hash)、数据流(stream)、列表(list)、集合(set)、有序集合(sortedset)。针对不同的value结构,Redis提供了不同的命令供用户使用。

当value为散列结构时,我们称之为散列相关命令。为了与Redis中的key-value散列做区分,我们称value的散列结构的键值对为field-value(域值对)。

第13章 列表相关命令的实现

Redis列表对象的底层数据结构是quicklist,我们在第7章已经详细讲述了quicklist的数据结构以及常见操作,本章我们主要讲解如何使用quicklist实现列表相关的命令。

第14章 集合相关命令的实现

Redis的set实现了无序集合,集合成员唯一。set底层基于dict和intset,在学习集合命令前,需要先了解dict和intset的结构,详见相关章节的介绍。

第15章 有序集合相关命令的实现

在第14章中,主要讲解了集合(Set)相关的命令,集合是无序的,而本章主要介绍有序集合(SortedSet)相关命令的实现,包括基本操作,比如zadd/zrem/zscan等,批量的操作(zrange/zremrange),以及集合相关的操作(交集zinterstore和并集zunionstore)。

有序集合中,用到的关键数据结构是ziplist以及 dict和skiplist,当服务器属性
server.zset_max_ziplist_entries的值大于0且元素的member长度小于服务器属性server.zset_max_ziplist_value的值(默认为64)时,使用的是ziplist,否则使用的是dict和skiplist。对于这三种数据结构,请参考第3、4和5章。

第16章 GEO相关命令

在生活中,位置信息十分重要,精确地对每个物体进行定位是我们进行其他相关操作的基础。Redis提供了一些命令来帮助我们有效地处理位置信息,比如计算两点间的距离,这类命令统称为GEO相关的命令,本节将详细介绍这类命令是如何实现的。

geohash算法在2008年公开,该算法可以把二维的经纬度信息降维到一维,并通过Base32编码将其转换为字符串。Ardb的作者提供了geohash-int的实现。Redis的核心开发者Matt借鉴Ardb的GEO功能,于2014年以module方式开发了Redis的GEO。2016年,在Redis 3.2中正式加入了GEO。本节主要学习geohash算法的实现,以及Redis中是如何使用该算法的。

第17章 HyperLogLog相关命令的实现

在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV (Page View,页面访问量)或者URL的访问次数,可以使用Redis提供的incr或incrby命令轻松实现,但像UV (Unique Visitor,独立访客)、独立IP数、搜索记录数等需要去重和计数的问题该如何解决呢?我们把这类求集合中不重复元素个数的问题称为基数计数。

解决基数计数有多种方法,简单来说,可以将数据存储在MySQL表中,使用distinctcount语句来计算不重复个数,也可以使用Redis提供的hash、set、bitmap等数据结构来处理,而且结果数据都非常精确,但是这些方法都会随着数据的不断增多,而导致占用的空间越来越大,对于非常大的数据集是不切实际的。那么是否能够降低一定的精度来平衡存储空间呢。有一类算法基于概率,仅使用常量和小量的内存来提供集合中唯一元素数量的近似值。

第18章 数据流相关命令的实现

Redis 5.0.0引入了Stream,本章主要介绍Stream相关命令的底层实现。

在Stream的实现中,用到的关键数据结构是rax、listpack。其中rax用于快速索引;listpack用于存储具体的消息,这些数据结构的详细介绍请参见第8章。

第19章 其他命令

该章节主要讲解事务命令、发布-订阅命令和Lua脚本命令3个部分。通过该章的学习,读者可以了解Redis中事务、发布–订阅的实现原理及其适用范围,以及Redis如何执行Lua脚本命令。

第20章 持久化

Redis是一个内存数据库,当机器重启之后内存中的数据都会丢失。所以对Redis来说,持久化显得尤为重要。Redis有两种持久化方式:一种为RDB方式,RDB保存某一个时间点之前的数据;另一种为AOF方式,AOF保存的是Redis 服务器端执行的每一条命令。两种方式各有优劣,在接下来的章节中会详细介绍。我们先通过在客户端输入info命令,查看Redis服务端记录的相关持久化状态信息,然后分别详细介绍RDB和AOF。

第21章 主从复制

Redis支持主从复制功能,用户可以通过执行slaveof命令或者在配置文件中设置slaveof选项来开启复制功能。例如,现在有两台服务器——127.0.0.1:6379和127.0.0.1:7000,向服务器127.0.0.1:6379发送下面命令:

127.0.0.1:6379>slaveof 127.0.0.1 7000
OK

此时服务器127.0.0.1:6379会成为服务器127.0.0.1:7000的从服务器(slaver),服务器127.0.0.1:7000会成为服务器127.0.0.1:6379的主服务器( master);通过复制功能,从服务器127.0.0.1:6379的数据可以和主服务器127.0.0.1:7000的数据保持同步。

本章将为读者详细介绍主从复制功能的源码实现。

第22章 哨兵和集群

哨兵是Redis 的高可用方案,可以在Redis Master发生故障时自动选择一个Redis Slave切换为Master,继续对外提供服务。集群提供数据自动分片到不同节点的功能,并且当部分节点失效后仍然可以使用。

本章首先介绍Redis哨兵的实现,然后介绍集群的实现。

限于文章篇幅原因,就展示到这里了,有需要的小伙伴可以查看下方名片↓↓↓ 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值