Why Redis?
- Redis 是一种运行速度很快,并发很强,跑在内存上的 NoSql 数据库,反对键到五种数据类型的映射。依据 Redis 官网提供的 benchmark 测试数据,redis 读的速度是 110000 次 /s, 写的速度是 81000 次 /s,并且试验证实,数据没在缓存的时候,雷同条件下用 Jmeter 进行压测,redis 的申请处理速度比 MySQL 高了 7 倍。另外,在工夫局部性原理很强的场景下,Redis 能够从缓存迅速响应,而不是去数据库查 sql,尤其是曾经放入缓存的数据,这体现出了 Redis 的 高性能;
- Redis 是单线程的,防止了多线程上下文的切换和锁竞争的工夫开销。(在 Redis6.0 之后在网络读写时已替换成多线程,但执行命令依然是单线程)
- Redis 指令是原子性的,高并发时不会产生数据异样,Redis 应用 I/O 多路复用技术,能够解决高并发的连贯 (非阻塞 I /O),这意味着可能让一个计算单元来解决来自多个客户端的流申请实现 高并发。
想要深刻理解 Redis,这本《Redis 设计与实现》就无奈绕开了。
第一局部 数据结构与对象
简略动静字符串 SDS
SDS 对标的是 C 语言的 String,通过在底层实现数组 buf 的根底上减少 len 和 free 字段,实现了
- 常数复杂度获取字符串长度
- 杜绝缓冲区溢出
- 缩小批改字符串时带来的内存重调配次数
实现的原理也巨简略,,,C 的 String 不记录 len,每次都只能遍历 String 工夫复杂度 O(n),SDS 空间换工夫用一个 len 记录一下,工夫复杂度间接降到 O(1), 这就能解释下面的 1 和 2,至于 3 就是 free 这个字段的作用了,redis 应用了空间预调配和惰性空间开释策略,说白了就是 SDS 批改之后如果变长了,理论调配的空间不仅仅是 len,会依据 SDS 长度定,如果新的 SDS 小于 1M,新的 SDS 大小就在原根底上 double+1,为啥 double,因为这里会多调配一倍给 free,这就是空间预调配;为啥 +1byte,因为最初一个字节保留空字符,为啥保留空字符,为了更好的兼容 C 语言对字符串的操作,对的,没有看错,Redis 底层就是用的规范 C 语言实现的。如果新的 SDS 大于 1M,free 就等于 1M,新的 SDS 就等于旧的 SDS+1M+1byte。
C 语言中对 String 进行的各种操作,SDS 天然也有对应的 API,详见 http://redisbook.com/preview/…
链表
因为 C 语言没有将链作为内置数据结构,Redis 用 ListNode 和指针实现了双向链表
typedef struct listNode{
struct listNode *prev;
struct listNode *next;
void *value;
}listNode;
未完待续。
参考:黄健宏. Redis 设计与实现[M]. Ji xie gong ye chu ban she, 2014.
https://zhuanlan.zhihu.com/p/…
https://youle.zhipin.com/ques…