数据结构
string
hash
list
set
sortedset
内存方面
内存分配器
在Redis中内存分配器在分配内存的时候是按照一系列固定的大小进行分配的,而不是按需分配的,2^n次进行match 比如23B的话就需要32B了呢
AOF
AOF重写是用来精简过大的AOF文件,加速Redis实例恢复,此任务是主线程fork子进程来完成。
RBD
RDB机制用来生成快照,用于实例恢复或是主从库复制。
RBD快照是通过主线程fork子进程来完成
切片机制是将数据分散到多个实例保存,用于保存大量数据。
命名规范
- 一个redis默认支持16个数据库,可以把不同业务分离到不同的数据库中去,但是如果要用不同的数据库的话,客户端需要用SELECT指令进行操作,从而多了一步步骤。 因此我们可以通过
业务名+:+业务数据+业务数据名来进行分割 比如 uv:page:1024 表示的是独立访客对应的页面标号为1024
Tips: 因为key本身也是字符串,底层的数据结构为SDS,因此会包含字符串长度,分配空间大小等元数据信息,从Redis3.2开始,当key字符串的长度增加的时,SDS的元数据也会占用更多的内存空间
所以为了减少key所占用的内存空间,可以将message简写为m,user简写为u,unique visitor使用uv
-
避免使用bigKey Redis是使用单线程读写数据的,所以bigkey的读写将会阻塞线程。 bigkey通常有两种情况。
-
使用高效序列化方法和压缩方法
-
使用整数对象共享池
命令使用规范
线上禁用的部分命令
- KEYS 按照键值对的key进行匹配,需要对Redis的全局哈希表扫描,严重阻塞Redis主线程;
- FLUSHALL 删除Redis实例上的所有数据,如果数据量大,会阻塞主线程;
- FLUSHDB 删除当前数据库中的数据,如果数据量大,同样会阻塞主线程
tips 对于keys而言,可以用scan来代替,分批返回符合条件的键值对
慎用monitor命令
因为在使用monitor命令之后,会持续输出检测到的各个命令操作,所以我们通常会使用monitor命令返回的结果,检查命令的执行情况。 但是monitor命令会把监控到的内容持续写入输出缓冲区,如果线上命令的操作很多,输出缓冲区就容易溢出。 所以可以短暂时间使用比如监控用户短时间的操作hhhhhh!
慎用全量操作命令
对于集合类型的数据来说,如果想要获得集合中的所有的元素,一般不建议使用全量操作的命令如(Hash类型的HGEIALL,Set类型的SMEMBERS),这些操作会对Hash和Set类型的底层数据结构进行全量扫描,阻塞主线程!~
Tips
- 可以用SSCAN、HSCAN命令分批返回集合中的数据,减少对主线程的阻塞。
- 化整为0,把一个大的Hash拆分多个小的Hash集合,这个操作对应到业务层就是把业务数据进行拆分,按照时间、地域、用户ID等属性拆分成多个小集合数据。
- 如果是集合类型保存的是业务数据的多个属性,而每次查询时,都需要返回这个属性的话,可以使用String类型,将这些属性序列化后保存,每次返回String即可,不需要对集合类型进行全量扫描。
Redis 6.0 新特性
- 面向网络处理的多IO线程 可以提升网络请求处理的速度 从网络IO处理到实际的读写命令处理都是由单个线程完成的。 随着网络硬件的性能能提升,Redis的性能瓶颈有时候会出现在网络IO的处理上,也就是说单个主线程处理网络请求的速度跟不底层网络硬件的速度
- 服务端协助的客户端缓存功能 跟踪功能
可以让应用直接在客户端本地读取数据 - 细粒度的权限控制 让Redis按照命令粒度控制不同用户的访问权限,加强Redis的安全防护
- RESP3协议的使用
增强了客户端的功能,可以让应用更加方便地使用Redis的不同数据类型
常见问题
1. redis变慢
体检:,最简单的方法就是查看redis的响应延迟,基线性能(-intrinsic-latency),可以用来监测和统计测试期间内的最大延迟。
./redis-cli --intrinsic-latency 120
Max latency so far: 1 microseconds.
Max latency so far: 3 microseconds.
Max latency so far: 13 microseconds.
Max latency so far: 35 microseconds.
1973503106 total runs (avg latency: 0.0608 microseconds / 60.81 nanoseconds per run).
Worst run took 427181x longer than the average latency.
我这边最大的延迟是35微秒,则该基线性能为35微秒。 如果你观察到Redis运行时的延迟是其基线性能的2倍以上,就可以认定Redis变慢了 因为在虚拟环境中运行的Redis由于增加了虚拟化软件层和真实的物理机相比,必然会引入一定的性能开销,所以基线性能会提高一些。
Max latency so far: 1 microseconds.
Max latency so far: 38 microseconds.
Max latency so far: 218 microseconds.
治疗:,因此要根据Redis的工作原理,与操作系统、存储以及网络等外部关键机制,再借助一些辅助工具来定位。
慢查询命令
所谓的慢查询命令,就是指在Redis中执行速度慢的命令,这会导致Redis延迟增加。
比如说Value类型为String的时候,GET/SET操作主要就是操作Redis的哈希表索引,这个命令的时间复杂度是固定的为O(1)。
但是当Value为Set的时候,SORT,SUNION/SMEMBERS的操作复杂度分别为O(N+M*log(M))和O(N)。其中N为Set中的元素个数,M为SORT操作返回的元素个数。
其实还有一种比较容易忽略的慢查询命令,那就是KEYS。
面对大量的慢查询命令,有两种处理方式
- 用其他高效命令代替。比如说不要使用SMEMBERS,而是要使用SSCAN多次迭代返回,避免一次返回大量的数据,造成线程的阻塞。
- 当你需要执行排序、交集、并集操作的时候,可以在客户端完成,而不要用SORT,SUNION,SINTER这些命令,以免拖慢Redis实例
过期操作
它是Redis用来回收内存空间的常用机制,应用广泛,但是会引起Redis操作阻塞,导致性能变慢
具体的算法如下:
文件系统:AOF模式
AOF有三种日志写回策略:no、everysec、always。这三种写回策略依赖文件系统的两个系统调用完成,也就是write和fsync。
| AOF写回策略 | 执行的系统调用 |
|---|---|
| no | 调用write写日志文件,由操作系统周期性地将日志写回磁盘 |
| everysec | 每秒调用一次fsync,将日志写回磁盘 |
| always | 每执行一个操作,就调用一次fsync将日志写回磁盘 |
在使用everysec时,Redis允许丢失一秒的操作记录,所以Redis主线程并不需要确保每个操作记录日志都写回磁盘。而且fsync的执行时间很长,如果实在Redis主线程中执行fsync,就容易阻塞主线程,所以当写回策略为everysec的时候,Redis会everysec使用后台的子线程完成fsync的操作。
然而对于always策略来说,Redis需要确保每个操作记录日志都写回磁盘,如果用后台子线程异步完成,主线程就无法及时地知道每个操作是否完成了,所以 always策略不使用后台子线程来执行。
潜在风险点
AOF重写会对磁盘进行大量IO操作,同时,fsync又需要等到数据写到磁盘后才能返回,所以,当AOF重写压力较大的时候,就会导致fsync被阻塞。虽然fsync是由后台子线程负责执行的,但是主线程会监控fsync的执行进度。
swap
操作系统本身会在后台记录每个进程的swap情况,即有多少数据量发生了wasp。 可以通过
redis-cli info | grep process_id