1. redis 为什么快?
在底层上, redis 使用了 IO 多路复用技术,像 select、epoll 等。能较好的保障吞吐量。而且 redis 采用了单线程处理请求,避免了线程切换和锁竞争锁带来的额外消耗。
加上 redis 本身也对一些数据结构进行了优化设计,所以 redis 的性能非常好,官方给出的测试报告是单机可以支持约 10w/s 的 QPS。
2. Redis 有哪些使用场景?应用是怎么样的?
Redis 的使用场景有很多,最常用的莫过于数据缓存了。但由于它提供了多种数据类型,因此我们还可以进行其他场景的开发,比如:
- 排行榜:有序集合(sorted set)每次写入都会进行排序,而且不含重复值,所以我们可以将用户的唯一标识,比如 userId 作为 key,分数作为 score,然后就可以进行
ZADD
操作,以得到排行榜。 - 签到:签到往往只有 2 种状态,已签到和未签到。这就跟 0 和 1 一样,所以 redis 的
setbit
、getbit
这种对位的操作就适合签到场景。 - 计数:redis 是单线程操作,这种计数功能,比如点赞数、粉丝数的操作可以交给 redis 以避免并发竞争问题。当然,也得考虑持久化问题。
3. Redis 通信协议 是怎么样的?
redis 采用文本序列化协议,和 http 协议一样,一个请求一个响应,客户端接到响应后再继续请求。也可以发起多次请求,然后一次响应回所有执行结果,即所谓的 pipeline 管道技术。
redis 的文本序列化协议比较简单,通过一些规范格式去解析文本,大概如下:
- rn 表示解析结束
- 简单字符串,以“ ”开头
- 错误 Errors,以“-”开头
- 整数类型,以“:”开头
- 大字符串类型,以“$”开头
- 数组类型,以“*”开头
例如,客户端向服务器发送命令:
SET key value
将被解析为:
*3rn$3rnSETrn$3rnkeyrn$5rnvaluern
上面的命令可以看成:
代码语言:txt复制*<参数数量> CR LF
$<参数 1 的字节数量> CR LF
<参数 1 的数据> CR LF
...
$<参数 N 的字节数量> CR LF
<参数 N 的数据> CR LF
而服务器的回复则有很多类型,一般由响应数据的第一个字节决定:
代码语言:txt复制状态回复(status reply)的第一个字节是 " "
错误回复(error reply)的第一个字节是 "-"
整数回复(integer reply)的第一个字节是 ":"
批量回复(bulk reply)的第一个字节是 "$"
多条批量回复(multi bulk reply)的第一个字节是 "*"
例如,响应回来的状态回复如下:
OK
4. redis 对外提供了哪些数据类型,它们的底层数据结构又是怎么样的?
为了让开发者能更好的使用缓存,redis 支持了 5 种数据类型。底层是由 6 种数据结构组成的。
5 种数据类型
字符串:字符串类型是 redis 里最基础的数据类型,像 set name "hello"
操作后,在 get name
时返回的就是字符串,而且还支持了对位的操作。一般一个键能存储 512MB 的值。
hash:哈希类型主要是用来存储对象的,一般我们如果有一整个对象要存储,里面包含了多个字段,则可以使用 hash 来存储,因为 redis 提供了对这些字段的提取和设置,减少了开发者对它的二次处理,比如序列化反序列化操作。
list:一个简单的字符串列表,它允许我们从两端进行 push,pop 操作,还支持一定范围的列表元素。可以看成是双向列表。
set:集合是一个不重复值的组合,为我们提供了交集、并集、差集等操作,像找出共同好友这种需求就可以使用集合操作了。
sorted set:有序集合,在上面集合的基础上提供了排序功能,通过一个 score 属性来进行排序。
6 种底层数据结构
上面的数据类型实际上在 redis 底层是有对应的数据结构来实现的,都是 redis 经过精心设计的,能很好的提高处理效率。
简单动态字符串:redis 是使用 C 语言写的,而 C 语言里的字符串类型比较原始,比如使用