Redis技能熟练掌握之十年内功
- 1.redis是什么?为什么要使用redis?
- 2.redis一般应用于什么场景(四个场景)?
- 3. Redis持久化机制是什么?各自的优缺点?一般咋么用?
- 4. redis五个基础类型支持的操作?
- 5. Redis 的对象机制(redisObject)?
- 6. Redis数据类型有哪些底层数据结构?
- 7. Redis RDB触发方式有什么
- 8. Redis边读边写如何保存内存数据一致性的?
- 9.RDB快照操作的时间内,如果发生服务崩溃咋么办?
- 10. AOF是写前日志还是写后日志?
- 11.如何实现AOF的?
1.redis是什么?为什么要使用redis?
redis是一种支持key-value等多种数据结构的存储系统,可用于缓存,事件发布与订阅,高速队列等场景,支持网络,提供字符串,列表,哈希,集合结构,直接存取,基于内存,可持久化。
- 读写性能优异
- Redis能读的速度是11w次/s,写的速度是8.1w次/s
- 数据类型丰富
- Redis支持二进制案例的Strings,lists,hashes,Sets及OrderedSets数据类型操作。
- 原子性
- Redis的所有操作都是原子性的,同时redis还支持对几个操作合并后的原子性操作。
- 丰富的特性
- redis支持publish/subscribe,通知,key过期等特性。
- 持久性
- redis支持AOF,RDB等持久化方式。
- 发布订阅
- 分布式
- Redis cluster。
2.redis一般应用于什么场景(四个场景)?
- 热点数据的缓存
1.1 缓存是Redis最常见的应用场景,之所有这么使用,主要是因为Redis读写性能优异。而且逐渐有取代memcached,成为首选服务端缓存的组件。而且,Redis内部是支持事务的,在使用时候能有效保证数据的一致性。
- 限时业务的应用
2.1 redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。
- 计数器的相关问题
redis由于incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务还体现在比如限制一个手机号发多少条短信、一个接口一分钟限制多少请求、一个接口一天限制调用多少次等等。
- 分布式锁
这个主要利用redis的setnx命令进行,setnx:"set if not exists"就是如果不存在则成功设置缓存同时返回1,否则返回0 ,这个特性在后台中有所运用,因为我们服务器是集群的,定时任务可能在两台机器上都会运行,所以在定时任务中首先 通过setnx设置一个lock,如果成功设置则执行,如果没有成功设置,则表明该定时任务已执行。 当然结合具体业务,我们可以给这个lock加一个过期时间,比如说30分钟执行一次的定时任务,那么这个过期时间设置为小于30分钟的一个时间就可以,这个与定时任务的周期以及定时任务执行消耗时间相关。
3. Redis持久化机制是什么?各自的优缺点?一般咋么用?
- Redis持久化是吧当前进程数据生成快照保存到磁盘上的过程,针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决。
- AOF 是“写后”日志,Redis先执行命令,把数据写入内存,然后才记录日志。日志里记录的Redis收到的每一条命令,这些命令以文本的形式保存。
- Redis4.0提出了混合使用AOF日志和内存快照的方法,简单来说,内存快照以一定的频率执行,在两次快照之间,使用AOF日志记录这期间的所有命令操作。
这样一来,快照就不用频繁地执行,这就避免了fork对主线程的影响,而且,AOF日志也只用于记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现日志文件过大的情况了,也可以避免重写开销。
如:T1和T2时刻的修改,用AOF日志记录,等到第二次坐全量快照时,就可以清空AOF日志,因为此时的修改都已经记录到快照里了,恢复就不再用日志了。
好处
:这个方法既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势, 实际环境中用的很多。
4. redis五个基础类型支持的操作?
- 字符串
1.1 字符串可以是整型、浮点型,数字类型可以自增或自减;
1.2 字符串类型的话,可以对子付出进行操作- 列表list
2.1 一个链表,链表每个节点都是一个字符串
2.2 对链表的两端进行push和pop操作,读取单个或多个元素,根据值查找或删除元素;- 哈希Hash
3.1 包含键值对的无序散列表
3.2 包含方法有添加、删除、获取单个元素- Set集合
4.1 包含字符串的无需集合
4.2 方法:添加、删除、获取、还包含计算交集、并集、差集等- Zset集合
5.1 和散列一样,用于存储键值对
5.2 字符串成员与浮点数之间有序映射;元素的排列顺序由分数大小决定,方法包含了添加、获取、删除、以及根据分数范围或成员获取元素。
5. Redis 的对象机制(redisObject)?
- 提供了统一访问不同数据结构的接口
- 提供了类型泛型,通过不同的类型泛型推断,优化存储结构
/*
* Redis 对象
*/
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码方式
unsigned encoding:4;
// LRU - 24位, 记录最末一次访问时间(相对于lru_clock);
// 或者 LFU(最少使用的数据:8位频率,16位访问时间)
unsigned lru:LRU_BITS; // LRU_BITS: 24
// 引用计数
int refcount;
// 指向底层数据结构实例
void *ptr;
} robj;
6. Redis数据类型有哪些底层数据结构?
Redis 设计的底层数据结构分为:如下
- 简单动态字符串 - sds
- 用于存储字符串值的数据结构
- 特点包含:
-
- 动态扩展,避免字符串缓冲区溢出
-
- 常数级获取字符串长度
-
- 可修改性: 可以对字符串进行修改操作,如追加、删除、替换等
-
- 二进制安全:可以存储任意二进制数据,不仅可以鵆文本字符串,还可以存储图片、视频等二进制数据。
- 空间预分配和惰性空间释放
- Redis字符串类型最多可以容纳512MB数据。
- 压缩列表 - ZipList
- 快表 - QuickList
- 字典/哈希表 - Dict
- 整数集 - IntSet
- 跳表 - ZSkipList
7. Redis RDB触发方式有什么
- 手动触发
1.1 save命令:阻塞当前redis服务器,直到RDB过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上不建议使用。
1.2 bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短,bgsave流程图如下所示:
- 自动触发
2.1 redis.conf中配置save m n ,即在m秒内有n次修改时,自动触发bgsave生成rdb文件;
2.2 主从复制,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点
2.3 执行debug reload命令重载redis时也会触发bgsave操作;
2.4 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作;
8. Redis边读边写如何保存内存数据一致性的?
思考
:rdb由于生产环境下我们为redis开辟的内存空间区域都比较大,比如6gb,那么将内存中的数据同步到硬盘的过程可能就会持续比较长的时间,而实际情况是这段时间redis服务一般都会接收到新的写操作请求
。那么如何保证数据一致性
呢?
从两方面说:
- RDB的核心思路是copy-on-write,来保证在进行快照操作的这段时间,需要压缩写入磁盘上的数据在内存不会发生变化。一方面,redis主进程会fork一个新的快照进程专门来做这个事情,这样保证了redis服务不会停止接收客户端包括写请求在内的任何请求;
- 另一方面,这段时间发生变化的数据会以副本的方式存放在另一个新的内存区域,待快照操作结束后才会同步到原来的内存区域。
9.RDB快照操作的时间内,如果发生服务崩溃咋么办?
在没有将数据完全写入到temp rdb file(或磁盘)前,这次快照操作都不算成功。如果出现了服务崩溃的情况,将上一次完整的rdb快照文件作为恢复内存数据的参考。也就是说,在快照过程中不能影响上一次的备份数据。redis服务会在磁盘上创建一个临时文件进行数据操作,待操作成功后才会用这个临时文件替换掉上一次的历史备份。
10. AOF是写前日志还是写后日志?
AOF日志采用的写后日志,即先写内存,后写日志。
Q:为什么采用写后日志(针对AOF)?
A:
- 避免额外的检查开销,Redis AOF写前日志,肯定需要对命令正确性校验,否则redis使用日志恢复数据时,就可能出错;但写后日志就不用再次检查了。
- 不会阻塞当前的操作
但这种也存在潜在风险:
- 如果命令执行完成了,写日志前宕机了,会丢失数据。
- 主线程写磁盘压力大,导致写盘慢,阻塞后续操作。
11.如何实现AOF的?
AOF日志记录了redis的每个命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync)。
- 命令追加:当aof持久化功能打开了,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的aof_buf缓冲区。
- 文件写入和同步:关于何时将aof_buf缓冲区的内容写入aof文件中,redis提供了三种写会策略。
- always:同步写回,每个命令执行完,立马同步地将日志写回磁盘
- EverySec: 每秒写回,每个命令执行完,只是先把日志写到 AOF文件内存缓存区,每隔一秒把缓存区中的内容写入磁盘。
- No,操作系统控制的写回,每个命令执行完,只是先把日志写到AOF文件的内存缓存区,由操作系统决定何时将缓存区写回磁盘。
三种写回策略的优缺点
:
上面三种写回策略体现了一个重要原则:trade-off
,取舍,指在性能和可靠性保证之间做取舍。
关于AOF的同步策略是涉及到操作系统的write函数和fsync函数的,在《redis设计与实现》中这样说明的:
- 为了提高文件写入效率,在现代操作系统中,当用户调用write函数,将一些数据写入文件时,操作系统通常会将数据暂存到一个内存缓存区里,当缓存区的空间被填满或者到了指定时限后,才真正将缓存区中的数据写到磁盘里。
- 这样的操作虽然提高了效率,但也为数据写入带来了安全问题,如果计算机停机,内存缓存区的数据会丢失。为此,系统提供了fsync,fdatasync同步函数,可以强制操作系统立刻将缓存区中的数据写会到硬盘里,从而确保写入数据的安全性。