面向面试知识-Redis
什么是Redis
运行于内存的基于key-value的非关系型数据库。
一款开源的内存数据结构存储,用作数据库、缓存、消息代理等。(可以基于Redis实现分布式锁、以及消息队列)
发布订阅??
对数据类型的操作都是原子性的,因为执行命令由单线程负责,不存在并发竞争的问题。
除此之外,Redis还支持:
Redis与Memcached的区别?
Redis和Memcached的共同点:
- 都是基于内存的数据库,性能都很高,一般可以用做缓存;
- 都有过期策略。
Redis和Memcached的区别:
- Redis支持的数据类型更加丰富(String、Hash、Set、List、Zset);而Memcached只支持最简单的key-value数据类型;
- Redis支持数据的
持久化,如何持久化??
,可以将内存中的数据保持在磁盘中,重启时可以再次加载使用;而Memcached没有持久化功能; - Redis原生支持集群;
- Redis支持订阅模型、Lua脚本、事务等功能,而Memcached不支持。
为什么使用Redis作为MySQL的缓存
主要是因为高性能和高并发
- Redis具备高性能
运行在内存的key-value缓存,读取速度快。
但是需要一定的方法解决Redis和MySQL数据库数据一致性的问题。 - Redis具备高并发
单台设备的Redis的QPS(Query Per Second),是MySQL的10倍,Redis单机的QPS能轻松破10w,而MySQL单机的QPS很难破1W。
因此可以考虑把数据库的部分数据转移到缓存中,这样会直接到缓存而不用经过数据库。
Redis的数据类型
类型类型:存储的值:结构的读写能力;
String字符串;缓存对象、常规计数、分布式锁、共享session信息等;
Hash哈希;缓存对象、购物车等??
List列表;消息队列(有两个问题①生产者需要自行实现全局唯一;②不能以消费组形式消费数据等;);
Set集合;聚合计算(并集、交集、差集)场景,比如点赞、共同关注、==抽奖活动,为嘛?==等
Zset有序集合;排序场景,比如排行榜、电话和姓名排序等。
Redis常见数据类型:
数据类型:存储的值:结构的读写能力
Redis各数据类型的数据结构实现:
- String类型内部实现:
主要是SDS,Simple Dynamic String,简单动态字符串。
- SDS不仅可以保存文本数据,还可以保存二进制数据。
- SDS获取字符串长度的时间复杂度为O(1)。
- Redis的SDS API是安全的,拼接字符串不会造成缓冲区溢出。
- List类型内部实现:
底层数据结构是由双向链表或压缩列表实现的:
- if 列表元素个数小于512,每个item的值都小于64字节,Redis会使用List类型的底层;
- else 使用双向链表;
在Redis3.2之后,List数据类型的底层DS只由quickList实现。
- Hash类型内部实现:
压缩列表或者哈希表
- if 列表元素个数小于512,且所有值小于64字节,用压缩列表;
- else 使用Hash表;
Redis 7.0之后只由quickList实现
- Set类型内部实现:
Hash表或者整数集合实现
- if 集合中的元素都是整数,且元素个数小于512,使用整数集合;
- else 使用哈希表;
- Zset类型内部实现
压缩列表或者跳表:
- if 有序集合的元素个数小于128个,且所有元素的值小于64个字节时,使用压缩列表;
- else 使用跳表;
Redis7.0之后使用listpack实现。
Redis的线程模型
Redis是单线程吗?
在处理一系列请求时,即接受客户端请求,解析请求,进行数据读写等操作,返回数据给客服端的过程,是单线程;
但是Redis程序并不是单线程的,Redis在启动的时候,会启动后台线程(BIO)。
- Redis在2.6版本加了两个后台线程,分别处理关闭文件、AOF刷盘两个任务;
- Redis 4.0之后,新增了一个后台线程,用来异步释放Redis内存,也就是lazyfree线程。
详细内容见Redis 常见面试题
之所以 Redis 为「关闭文件、AOF 刷盘、释放内存」这些任务创建单独的线程来处理,是因为这些任务的操作都是很耗时的,如果把这些任务都放在主线程来处理,那么 Redis 主线程就很容易发生阻塞,这样就无法处理后续的请求了。
此图太大了,内容有点多,慢慢看一下;
为什么Redis采用单线程都能这么快?
- 运行在内存;
- 非多线程,避免了多线程竞争,免去了线程切换等的资源消耗;
- 采用I/O多路复用处理大量的客户端Socket请求;
Redis在6.0之后引入了多线程,但是主要面向I/O,采用了多个I/O线程来处理网络请求,因为随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络I/O的处理上。
Redis持久化
Redis如何实现数据不丢失
Redis运行在内存,当重启或者崩溃,内存中的数据会丢失,因此需要将数据保存至磁盘实现数据的持久化,在Redis重启后重新恢复保存在磁盘中的数据,避免数据丢失。
三种持久化方式:
- AOF日志:每执行一条写操作,就将该命令以追加的方式写入一个特定文件中。
- RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘。
- 混合持久化方式:集成了AOF和RDB的优点。
AOF日志是如何实现的?
RDB是如何实现的?
上两部分见参考:Redis 如何实现数据不丢失?
Redis的内存淘汰策略
Redis如何保证数据一致性
Redis如何解决数据一致性问题?
延迟双删