深入理解redis
一、什么是redis:Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:基于内存运行,性能高效支持分布式,理论上可以无限扩展key-value存储系统开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种
一、什么是redis:
Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
- 基于内存运行,性能高效
- 支持分布式,理论上可以无限扩展
- key-value存储系统
- 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
相比于其他数据库类型,Redis具备的特点是:
- C/S通讯模型
- 单进程单线程模型
- 丰富的数据类型
- 操作具有原子性
- 持久化
- 高并发读写
- 支持lua脚本
二、redis的五种类型:
1、String类型:最大长度支持512M
- GET/MGET
- SET/SETEX/MSET/MSETNX
- INCR/DECR
- GETSET
- DEL
2、哈希类型:
该类型是由field和关联的value组成的map。其中,field和value都是字符串类型的。
- HGET/HMGET/HGETALL
- HSET/HMSET/HSETNX
- HEXISTS/HLEN
- HKEYS/HDEL
- HVALS
3、列表类型:该类型是一个插入顺序排序的字符串元素集合, 基于双链表实现。
- LPUSH/LPUSHX/LPOP/RPUSH/RPUSHX/RPOP/LINSERT/LSET
- LINDEX/LRANGE
- LLEN/LTRIM
4、集合类型:
Set类型是一种无顺序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的。Set类型的底层是通过哈希表实现的:
- SADD/SPOP/SMOVE/SCARD
- SINTER/SDIFF/SDIFFSTORE/SUNION
5、顺序集合类型:
ZSet是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与Set类型一样,其底层也是通过哈希表实现的。
- ZADD/ZPOP/ZMOVE/ZCARD/ZCOUNT
- ZINTER/ZDIFF/ZDIFFSTORE/ZUNION
三、redis持久化:
1、RDB:
bgsave触发,Redis调用fork()函数,创建一个子进程(子进程与父进程共内存),子进程执行持久化操作,将内存中的缓存持久化到一个rdb临时文件,待到持久化完成,临时文件替换旧的dump.rdb文件。自此一次RDB持久化操作就完成了。
怎么解决子进程在持久化过程中,有新的写入请求呢?
这就用到了写时复制(copy-on-write):
1、子进程会就是把真实数据的地址拷贝一份到需要持久化的进程中,注意这边是拷贝地址,执行很快
2、Redis会开辟一块新的空间, 让写数据的地址指向新的空间,这里就是copy-on-write策略,持久化的还是修改之前的数据,修改的数据已经是复制出来的另一份数据了。
2、AOF:
AOF 持久化时,会将新写入的命令放入aof_buff中,然后检测时间(这个时间就是redis.conf中配置的aof执行频率),再决定是否持久化。当发生aof日志重写时,Redis同样会调用fork()函数,创建一个子进程,对当前内存中的数据进行持久化到一个临时aof文件,这个期间产生的写操作会存入缓冲区,待到持久化完成后,再将缓冲区的操作写入aof后面。
肯定不能每执行一条写入命令就记录到文件中,那会严重拖垮性能!所以准备一个缓冲区,然后把要记录的命令先临时保存在这里,然后再择机写入文件,我把这个临时缓冲区叫做aof_buf。
除aof_buf之外,又准备了一个缓冲区:AOF重写缓冲区
从创建重写子进程开始的那一刻起,我把后面来的写入命令也copy一份写到这个重写缓冲区中,等到子进程重写AOF文件结束之后,我再把这个缓冲区中的命令写入到新的AOF文件中。
最后再重命名新的AOF文件,替换掉原来的那个臃肿不堪的大文件,终于大功告成
四、主从复制:
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点
主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。
1、主从复制过程大体可以分为3个阶段:
连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段;
a、连接建立阶段
1)、保存主节点信息
2)、建立socket连接
3)、发送ping命令
4)、身份验证
5)、发送从节点端口信息
b、数据同步阶段
主节点和从节点互为客户端和服务端
c、命令传播阶段
主节点和从节点互为客户端和服务端
数据同步完成后,还有复制积压缓存区中的写命令没有执行,这样的话需要命令同步
2、全量复制和部分复制:
a、全量复制
Redis通过psync命令进行全量复制的过程如下:
(1)从节点判断无法进行部分复制,向主节点发送全量复制的请求;或从节点发送部分复制的请求,但主节点判断无法进行部分复制;具体判断过程需要在讲述了部分复制原理后再介绍。
(2)主节点收到全量复制的命令后,执行bgsave,在后台生成RDB文件,并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令
(3)主节点的bgsave执行完成后,将RDB文件发送给从节点;从节点首先清除自己的旧数据,然后载入接收的RDB文件,将数据库状态更新至主节点执行bgsave时的数据库状态
(4)主节点将前述复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据库状态更新至主节点的最新状态
(5)如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的最新状态
b、部分复制
部分复制的实现,依赖于三个重要的概念:
复制偏移量:主节点和从节点分别维护一个复制偏移量(offset),代表的是主节点向从节点传递的字节数;主节点每次向从节点传播N个字节数据时,主节点的offset增加N;从节点每次收到主节点传来的N个字节数据时,从节点的offset增加N。
复制积压缓冲区:是由主节点维护的、固定长度的、先进先出(FIFO)队列,默认大小1MB;当主节点开始有从节点时创建,其作用是备份主节点最近发送给从节点的数据。注意,无论主节点有一个还是多个从节点,都只需要一个复制积压缓冲区。
在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset)。由于复制积压缓冲区定长且是先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。
由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size);例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。
从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:
- 如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
- 如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制
服务器运行ID(runid):每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都不一样),由40个随机的十六进制字符组成;runid用来唯一识别一个Redis节点。
主从节点初次复制时,主节点将自己的runid发送给从节点,从节点将这个runid保存起来;当断线重连时,从节点会将这个runid发送给主节点;主节点根据runid判断能否进行部分复制:
- 如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
- 如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。
3、psync命令的执行
如果从节点之前未执行过slaveof或最近执行了slaveof no one,则从节点发送命令为psync ? -1,向主节点请求全量复制;否则发送命令为psync <runid> <offset>(其中runid为上次复制的主节点的runid,offset为上次复制截止时从节点保存的复制偏移量),主节点收到消息runid与从节点发送的runid相同,且从节点发送的offset之后的数据在复制积压缓冲区中都存在,则回复+CONTINUE,表示将进行部分复制,否则回复+FULLRESYNC <runid> <offset>,表示要进行全量复制
知识点:
Redis配置:redis配置文件详解 - AlanLee-Java - 博客园
NoSql:Sql Or NoSql,看完这一篇你就懂了 - 五月的仓颉 - 博客园
RDB和AOF(append only file):Redis的两种持久化RDB和AOF(超详细)_鲨鱼辣椒灬的博客-CSDN博客_rdb和aof
更多推荐
所有评论(0)