最近看了《Redis设计与实现》,从开始的基础数据类型到对象、事件、持久化、复制、sentinel。有一个大概的了解,利用回忆写一点作为复习增强记忆。
一.基础数据类型
1.SDS(simple dynamic string)简单动态字符串,结构体内包括:已使用长度len,空闲长度free和一个字符数组buf[]。具有以下的优点:
- 可以在常量O(1)时间内获取字符长度,len的值。strlen的时间复杂度为O(n)。可以避免获取字符长度成为性能的瓶颈;
- 不会产生溢出。例如:strcat()函数假定目标有足够的空间容纳拼接的字符,但实际可能出现溢出。而SDS则可以通过检测free的值来判断是否可以拼接
- 预分配和惰性释放。1.预分配:当buf中加入的字符长度大于free时,如果拼接后字符长度小于1M,分配len等长度的free;拼接后大于1M,分配1M的free。这样就将固定分配N次变为最多分配N次。2.惰性释放:当删除buf中字符时,不会直接释放空间,而是将len减少,free增加。这样当再次分配字符时就不用申请新的空间。
- 二进制安全。
- 如果存储的数据是字符时,可以直接使用系统字符串函数。
2.基本数据结构:链表、字典、跳跃表(较少使用)、压缩链表。
3.对象
4.事件:文件事件和时间时间。
5.持久化:RDB持久化和AOF持久化(数据是存储在内存中,容易丢失,持久化使将数据存储在磁盘中,再次开启redis-server时通过载入RDB或AOF文件恢复数据库。其中AOF是通过虚拟一个无网络连接的客户端执行语句进行恢复)
在AOF持久化处于关闭状态时才使用RDB持久化,RDB持久化是将数据库信息压缩快照。AOF持久化是通过保存数据库操作语句来重新生成数据。
RDB:SAVE和BGSAVE。SAVE阻塞服务器,BGSAVE是通过创建一个新进程调用SAVE操作生成RDB文件。
BGSAVE执行时,BGREWRITEAOF会被阻塞,推迟到BGSAVE之后执行。BGREWRITEAOF执行时,BGSAVE会被拒绝。
AOF:将数据库操作语言写入到AOF文件中,分为三种:1.每次执行语句都写入AOF文件,速度慢但是安全;2.每一秒写入一次,既考虑了速度又考虑安全,即时出错也只丢失一秒的数据操作;3.从不写入,用户自己控制写入,速度快但是不安全。(是将操作写入到AOF缓冲区中,写入是指将缓冲区中的数据写入到AOF文件)
当操作过多,有很多重复操作的语句是不必要的,这时就利用重写AOF来解决。在重写的过程中,服务器将执行数据库操作语句,并同时将语句添加到AOF缓冲区和AOF重写缓冲区,重写结束后,将重写缓冲区中的数据写入到AOF文件,并用新的AOF替换掉之前的AOF。
6.复制:分为同步和命令传播。(老版本的复制SYNC和新版本的复制PSYNC)
老版本的复制:从服务器通过向主服务器发送SYNC命令,主服务器生成一个RDB文件(同时将此时开始的命令写入到一个缓冲区中),将RDB文件发送给从服务器,从服务器进行同步(此时,主从服务器达到初步的一致),同步结束后,主服务器将缓冲区中的命令发送给从服务器。(此时,主从复制完成,达到同步)。此后只需要命令传播就可以实现复制。缺点:在从服务器断线重连后,需要重新进行一遍如上的步骤,而不是修改主从之间的差异。
新版本的复制:修复了老版本的缺点。从服务器向主服务器发送PSYNC命令,主服务器判断从服务器是否是第一次连接,是→SYNC,否→查看复制偏移量;偏移量是否相同:否→说明从服务器是断线重连的,只需要到复制积压缓冲区中找到对应的复制偏移量,是否找到,是→进行复制(部分重复制),否→SYNC(完整重复制)。
复制积压缓冲区:主服务器维护的一个固定长度的队列,每个字节对应着一个复制偏移量。从服务器可以从中查询要复制的偏移量是否还在其中。(大小一般为1M,可以根据需要调整)
复制过程(PSYNC):I.存储主节点的IP和port;II.创建socket连接(从服务器为主服务器的客户端);III.ping;IV.监听端口;V.身份验证(主从同时没设置密码,或同时设置密码且匹配才算成功),失败则重试;VI.复制(主从服务器互为对方客户端);VII.忘了
心跳机制:I.保持连接;II.作为辅助什么什么;III.判断是否有从服务器偏移量出现不同(断线重连的情况)。
7.sentinel:哨兵,监视主服务器。
今天刚看了一点,
sentinel会监视主服务器(master 1)和从服务器(slave 2,3,4),当主服务器(1)离线超过规定时间后,sentinel会将下一个服务器(2)作为主服务器(master 2),其他服务器(slave 3,4)作为它的从服务器,并继续监视之前的主服务器(1),若主服务器重连,则将它作为从服务器(将1作为当前master 2的一个从服务器)。
sentinel启动过程:I.启动初始化服务器(sentinel服务器不需要实现数据库功能,启动过程不同,不需要载入RDB或AOF文件,不能实现SET等数据库操作);II.将数据库语言转为sentinel(修改命令表,将SET等命令表修改为PING、INFO等命令表:共有7条命令);III.初始化sentinel(sentinelRedisStatus);IV.设置主服务器列表(设置上一步中的master(一个指向字典的指针)结构sentinelRedisNode);V.
有点遗忘,回忆的不全,明天再看一下。