Redis简介
Redis 是一个开源(BSD 许可)内存数据结构存储用作数据库、缓存、消息代理和流引擎。Redis 提供数据结构,例如 字符串、散列、列表、集合、带范围查询的排序集合、位图、超日志、地理空间索引和流。Redis 内置了复制、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久性,并通过以下方式提供高可用性Redis Sentinel和Redis Cluster的自动分区例如附加到字符串;
您可以 对这些类型运行原子操作,例如附加到字符串;增加哈希值;将元素推入列表;计算集交、并 、差;或获取排序集中排名最高的成员。
为了达到最佳性能,Redis 使用 内存中的数据集。根据您的用例,Redis 可以通过定期将数据集转储到磁盘 或将每个命令附加到基于磁盘的日志来持久化您的数据。如果您只需要一个功能丰富的网络内存缓存,您也可以禁用持久性。
Redis 支持异步复制,具有快速非阻塞同步和自动重新连接以及网络拆分上的部分重新同步
Redis 还包括:
·交易
发布/订阅。
Lua 脚本·
生命周期有限的密钥
·LRU 驱逐密钥自动故障转移
Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。
Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 List (列表)Set(集合)、Zset(有序集合)、Bitmaps(位图)、HyperLogLog(基数统计)、GEO(地理信息)Stream(流),并且对数据类型的操作都是原子性的,因为执行命令由单线程负责的,不存在并发竞争的问题。
除此之外,Redis 还支持事务 、持久化、Lua 脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布/订阅模式,内存淘汰机制、过期删除机制等等。
2.Redis 和 Memcached 有什么区别?
Redis 与 Memcached 共同点:
1.都是基于内存的数据库,一般都用来当做缓存使用;
2.都有过期策略;
3.两者的性能都非常高;
Redis与Memcached 区别
Redis 支持的数据类型更丰富(String、Hash、List、Set、ZSet),而 Memcached 只支持最简单的 key-value 数据类型;
Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用;而 Memcached 没有持久化功能,数据全部存在内存之中Memcached 重启或挂掉后,数据会丢失;
Redis 原生支持集群模式,Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;
Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。
3.为什么用 Redis 作为 MySQL 的缓存?
主要是因为 Redis 具备「高性能」和「高并发」两种特性
1.Redis 具备高性能
假如用户第一次访问 MVSQL 中的某些数据,这个过程会比较慢,因为是从硬盘上读取的:将该用户访问的数据缓存在 Redis 中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了,操作 Redis缓存就是直接操作内存,所以速度相当快。
2.Redis 具备高并发
单台攻备EKeds HQPS(Query Per >econd每秒钾处理完请來的次数)是MySQL的10倍Redis 单机的 QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w。
所以,直接访问 Redis 能够承受的请求是远远大于直接访问 MVSQL的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。
Redis 数据结构
1.Redis 数据类型以及使用场景分别是什么?
Redis 提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希)List(列表),Set(集合)、Zset(有序集合)
随着 Redis 版本的更新,后面又支持了四种数据类型:BitMap(2.2 版新增)、HyperLogLog(2.8 版新增)、GEO(3.2 版新增)、Stream(5.0 版新增)
Redis 五种数据类型的应用场景:
String 类型的应用场景:缓存对象、常规计数、分布式锁、共享 session 信息等。
·List 类型的应用场景:消息队列(但是有两个问题:1.生产者需要自行实现全局唯- ID;2.不能以消费组形式消费数据)等。
Hash 类型:缓存对象、购物车等
Set 类型:聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等。
Zset 类型:排序场景,比如排行榜、电话和姓名排序等。
Redis 后续版本又支持四种数据类型,它们的应用场景如下:
·BitMap(2.2 版新增):二值状态统计的场景,比如签到、判断用户登陆状态、连续签到用户总数等;
·HyperLogLog(2.8 版新增):海量数据基数统计的场景,比如百万级网页 UV 计数等:
·GEO(3.2 版新增):存储地理位置信息的场景,比如滴滴叫车;
Stream(5.0 版新增):消息队列,相比于基于 List 类型实现的消息队列,有这两
特有的特性:自动生成全局唯一消息ID,支持以消费组形式消费数据。
.五种常见的 Redis 数据类型是怎么实现?
2.1.1.String 类型内部实现
String 类型的底层的数据结构实现主要是 SDS(简单动态字符串)。 SDS 和我们认识的 C 字符串不太一样,之所以没有使用C 语言的字符串表示,因为 SDS 相比于C 的原生字符串:
- SDS 不仅可以保存文本数据,还可以保存二进制数据。因为 SDS 使用 len 属性的值而不是空字符来判断字符串是否结束,并且 SDS 的所有 API都会以处理二进制的方式来处理 SDS 存放在 buf 数组里的数据。所以 SDS 不光能存放文本数据,而且能保存图片、音频、视频、压缩文件这样的二进制数据;
- SDS 获取字符串长度的时间复杂度是 O(1)。因为 C语言的字符串并不记录自身长度,所以获取长度的复杂度为 O(n);而 SDS 结构里用 len 属性记录了字符串长度,所以复杂度为 O(1);
- Redis的SDS API是安全的,拼接字符串不会造成缓冲区溢出。因为SDS在拼接字符串之前会检查SDS 空间是否满足要求,如果空间不够会自动扩容,所以不会导致缓冲区溢出的问题。
2.1.2.List 类型内部实现
List 类型的底层数据结构是由双向链表或压缩列表实现的:
-
- 如果列表的元素个数小于 512 个(默认值,可由 list-max-ziplist-entries 配置),列表每个元素的值都小于 64 字节(默认值,可由 list-max-ziplist-value 配置),Redis 会使用压缩列表作为 List 类型的底层数据结构;
- 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构;
但是在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表。
2.1.3.Hash 类型内部实现
Hash 类型的底层数据结构是由压缩列表或哈希表实现的
- ·如果哈希类型元素个数小于 512 个(默认值,可由 hash-max-ziplist-entries 配置),所有值小于64 字节(默认值,可由 hash-max-ziplist-value 配置)的话,Redis 会使用压缩列表作为 Hash 类型的底层数据结构;
- 如果哈希类型元素不满足上面条件,Redis 会使用哈希表作为 Hash 类型的底层数据结构。
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了
2.1.4.Set 类型内部实现
Set 类型的底层数据结构是由哈希表或整数集合实现的:
- 如果集合中的元素都是整数且元素个数小于 512(默认值,set-maxintset-entries配置)个,Redis会使用整数集合作为 Set 类型的底层数据结构;
- 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构。
2.1.5.ZSet 类型内部实现
Zset 类型的底层数据结构是由压缩列表或跳表实现的:
- 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;
- 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;
在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了
Redis 线程模型
1.Redis 是单线程吗?
Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。
但是,Redis 程序并不是单线程的,Redis 在启动的时候,是会启动后台线程(BIO)的:
Redis 在 2.6 版本,会启动 2 个后台线程,分别处理关闭文件、AOF 刷盘这两个任务;
Redis 在 4.0 版本之后,新增了一个新的后台线程,用来异步释放 Redis 内存,也就是 lazyfree 线程。
关闭文件、AOF 刷盘、释放内存这三个任务都有各自的任务队列:
- ·BIO CLOSE FILE,关闭文件任务队列:当队列有任务后,后台线程会调用 close(fd),将文件关闭;
- BIO AOF FSYNC,AOF刷盘任务队列:当 AOF 日志配置成 everysec 选项后,主线程会把 AOF 写日志操作封装成一个任务,也放到队列中。当发现队列有任务后,后台线程会调用 fsync(fd),将 AOF文件刷盘,
- BIO LAZY FREE,lazy free 任务队列:当队列有任务后,后台线程会 free(obj)释放对象/free(dict)删除数据库所有对象/free(skiplist)释放跳表对象;