本文将大概介绍Redis的一些特性、使用场景。
incr
、incrby
等命令很好的支持了这计数功能。SET key value [EX seconds] [PX milliseconds] [NX|XX]
命令,以及Lua脚本功能,基于此能够很好的实现分布式锁功能。每种产品都有自己的特定的应用领域。Redis也不是万能的。
作为最佳实践本章将会把主要的关注点放和在Redis用户相关的一些Redis基本知识,这部分知识是Redis用户需要了解并在实际使用Redis过程中要考虑的。比如,如果不考虑Redis单线程的特性可能会遇到请求阻塞导致性能急剧下降的问题;不了解Redis的数据结构,可能导致使用存储膨胀、大value、热key的问题等等。
不管是单线程或者多线程都是为了提升Redis的性能,Redis作为一个基于内存的数据库,不仅仅需要进行数据的读写操作,还要处理大量的外部的网络请求,这就不可避免的要进行多次IO。Redis选择了IO多路复用+单线程的架构来处理请求。简单说:
相比其他KV数据库,Redis提供了丰富的数据结构来满足用户的不同需求。同时,可以说Redis在内存使用是锱铢必较。为了最大可能的节约内存,Redis的每一种数据结构都拥有2~3种(截止Redis6.0,后续可能会更多)的底层实现。比如,在list
、hash
、set
、zset
等复杂数据结构在数据量较小的情况下都会使用ziplist
这种数据结构等,由于ziplist
是连续空间,不影响指针等附加消耗,在数据量较小的时候读写速度劣势也并不明显,但是可以节约不少存储,尤其是在实际使用场景种往往小数据占比较大的情况下内存节约更为明显。表-1 Redis数据结构与编码
类型 | 编码 | 决定条件 | 说明 |
---|---|---|---|
string | int | 8 个字节的带符号长整型(2^63-1) | 整数编码 |
string | embstr | 小于等于 44 个字节的字符串,3.0.0 是 39 个字节 | 优化内存分配的字符串编码,和StringObject连续,一起分配一起释放,分别减少一次内存操作 |
string | raw | 大于 44 个字节的字符串 | 动态字符串编码 |
list | ziplist | value最大字节数 <= list-max-ziplist-value 且 链表长度 <= list-max-ziplist-entries | |
list | linkedlist | value最大字节数 > list-max-ziplist-value 或者 链表长度 > list-max-ziplist-entries | |
list | quicklist | 3.2版本之后新增。废弃list-max-ziplist-value 和 list-max-ziplist-value。使用新配置项:list-max-ziplist-size表示最大压缩空间或者ziplist长度,取值范围为[-5, -1]([64kb, 4kb])默认是-2(8kb);list-compress-depth 表示压缩深度,默认是0,不压缩 | 考虑到链表附加空间相对太高,使用quicklist代替ziplist 和 linklist |
hash | ziplist | value最大字节数 <= hash-max-ziplist-value 且 field个数 <= hash-max-ziplist-entries | |
hash | hashtable | value最大字节数 > hash-max-ziplist-value 或者 field个数 > hash-max-ziplist-entries | |
set | intset | 元素必须是整型,且集合长度<=set-max-inset-entries | |
set | hashtable | 集合长度>set-max-inset-entries | |
zset | ziplist | value最大字节数 <= zset-max-ziplist-value 且 链表长度 <= zset-max-ziplist-entries | |
zset | skiplist | value最大字节数 > zset-max-ziplist-value 或者 链表长度 > zset-max-ziplist-entries | |
stream | rax + listpack | listpack 是 ziplist 优化版本,目前(Redis 5.0.0)只使用在 stream 中 |
表1 Redis数据结构内部实现
Redis支持RDB和AOF两种持久化机制。持久化功能能够有效的避免Redis服务异常退出导致数据完全丢失的情况。当重启Redis服务会自动加载持久化文件即可完成数据恢复。
RDB持久化是将当前Redis进程数据快照保存到硬盘的过程,触发RDB生成有两种方式:手动触发和自动触发。
save
和bgsave
两个命令,其中save
是阻塞的,已逐步淘汰。save
相关配置,如save m n
,表示m
秒内数据发生了n
次修改,则字段执行bgsave
;bgsave
生成RDB文件并发送给从节点。debug reload
命令重新加载Redis,会触发save
操作(注意,这里是save
)。shutdown
命令,如果没有开启AOF持久化也会自动执行bgsave
。RDB是一个紧凑压缩的二进制文件(Redis默认使用LZF压缩算法对RDB进行压缩),是Redis在某一时刻的数据快照,有如下优点:bgsave
都执行fork
操作创建子进程,属于重量级操作,成本较高。AOF(append only file)持久化是以日志的方式记录每次写操作命令。重启Redis时,会通过重新执行这些命令的方式来恢复数据。AOF持久化有三点需要说明:
aof_buf
,然后通过提供的不同策略(always
、everysec
、no
)来将aof_buf
中的数据同步到磁盘上。为了解决分布式系统中服务单点问题,Redis引入了复制机制,实现主从架构以满足容灾和负载均衡等问题。复制本质上是数据同步的过程,Redis支持两种数据同步方式:
Redis官网
Redis开发与运维
How Twitter Uses Redis To Scale - 105TB RAM, 39MM QPS, 10,000+ Instances
Latency Numbers Every Programmer Should Know