Redis问答
1. 认识Redis
1.1 什么是Redis
Redis是一种基于内存的数据库,对数据的读写都在内存上操作,因此读写速度很快,常用于缓存、消息队列、分布式锁等的应用场景
Redis提供了很多数据类型来支撑各种场景,例如String、hash、list、set、zset、bitmapas、hyperloglog、GEO,对数据的操作都是原子性的,单线程过程,不存在锁的竞争
除此之外,Redis还支持事务、持久化、Lua脚本、集群方案、发布订阅模式等
1.2 Redis和Memcache有什么区别
Memcache也是基于内存的数据库,也可以用作缓存,和Redis一样都有过期策略,两者的性能都比较高
Redis优点:
- Redis支持的数据类型更多,比如String、list、set、zset、hash,Memcache只支持key-value类型的
- Redis支持持久化数据到磁盘,有利于数据恢复;Memcache没有持久化,重启或者宕机都会导致数据丢失
- Redis支持原生集群的模式,Memcache目前依赖客户端往集群中分片写入信息
- Redis还支持发布订阅模型、Lua脚本、事务等功能
1.3 为什么使用Redis作为MySQL的缓存
Redis属于高并发框架,具备高并发和高性能的特点
- 高性能:如果数据每次都是访问MySQL数据库,因为是从磁盘上读取数据,频繁的磁盘IO会导致程序非常慢,但是如果添加了Redis作为缓存,第一次访问时读取数据库然后存到缓存,后续就可以直接访问Redis,操作Redis是操作的内存,所以速度很快
- 高并发:单台Redis设备的QPS是MySQL的10倍,所以直接访问redis能承受的访问量是远大于MySQL的,所以会考虑部分数据缓存到Redis,并且Redis还有集群的模式
2. Redis的数据结构
1.1 Redis数据类型和使用场景
String、List、set、zset、hash
- String应用场景:于缓存对象、共享session、常规计数、分布式锁
- list应用场景:消息队列
- hash应用场景:缓存对象、购物车
- set:聚合计算场景,比如点赞、共同关注、抽奖活动
- zset:排序场景,比如排行榜
- BitMaps:二值状态统计的场景
- HyperLogLog:海量数据基数统计
- GEO:存储地理位置信息,例如滴滴叫车
1.2 Redis 数据类型内部实现
String:
String底层数据结构使用SDS(简单动态字符串),没有使用C语言字符串主要是
- SDS不仅能保存文本,还可以保存二进制数据(图片、音频、视频、压缩文件)
- SDS获取字符串长度的复杂度是O(1),因为SDS数据结构使用len属性记录了字符长度长度
- Redis的SDS API是安全的,不会出现缓冲区溢出,因为SDS在拼接字符串的时候都会检查空间是否足够,空间不够会自动扩容
List:
底层使用双向链表和压缩链表实现
当列表元素个数小于712,并且每个元素的大小不超过44字节时会使用压缩列表作为List类型的底层数据结构,否则使用双向链表
在Redis3.2以后list使用quickList代替压缩列表和双向列表
Set:
底层使用哈希表或者整数集合实现
当列表元素全是整数并且个数不超过712时使用的是整数集合作为Set的底层数据结构,否则使用哈希表
Zset
底层使用压缩列表或者跳表实现
当列表元素不超过128并且所又元素大小不超过44时使用压缩列表作为zset的数据结构,否则用跳表实现
Redis7.0以后压缩列表数据结构已经废弃,使用listPack数据结构实现
3. Redis线程模型
3.1 Redis是单线程的吗
Redis单线程指的是【接收客户端请求→解析请求→查询数据→返回客户端】这个操作是由一个主线程完成
但是Redis程序并不是单线程的,Redis程序在启动时还会