主要内容

慢查询
生命周期
如图所示为客户端请求到Redis的完整生命周期:发送命令、排队、执行命令、返回结果

- 慢查询发生在第三阶段(也就是说其他阶段像排队耗时都不算)
- 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素
两个配置
-
slowlog-max-len
1.配置慢查询队列最大长度
2.筛选出的慢查询会进入一个先进先出队列
3.该队列是固定长度的
4.该队列是保存在内存中 -
slowlog-log-slower-than
1.慢查询阈值(单位:微秒),也就是说超过多少时间的查询是慢查询
2.slowlog-log-slower-than=0; 记录所有命令
3.slowlog-log-slower-than<0; 不记录任何命令

配置方法
- 默认值
config get slowlog-max-len = 128
config get slowlog-log-slower-than = 10000 - 修改配置文件重启(不建议,因为生产环境要尽量避免重启,在第一次启动redis前可以这么做)
- 动态配置
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
三个命令
-
slowlog get [n]:
获取慢查询队列(n为可选参数,指定慢查询条数) -
slowlog len:
获取慢查询队列长度 -
slowlog reset:
清空慢查询队列
运维经验
-
slowlog-log-slower-than
不要设置过大,默认10ms,通常设置1ms -
slowlog-max-len
不要设置过小,通常设置1000左右 - 理解命令生命周期
- 定期持久化慢查询(方便查到历史慢查询操作)
pipeline
什么是流水线
对比: 1次网络命令通信模型 vs 批量网络命令通信模型

执行redis命令时间通常是非常快的,而网络则存在很多不稳定因素。另外redis虽然提供了mget、mset和hmget、hmset等这样的命令,但是如果我们需要同时执行get和hget命令需要怎么做呢,其实这就是流水线帮助我们实现的功能。
流水线就是将一批命令进行一个打包,而在服务端进行批量的计算,然后按顺序将结果返回给客户端,使用流水线可以大大节省网络的开销。

流水线的作用
两点说明:
1.redis的命令时间是微秒级别
2.pipeline每次条数要控制(网络)

分析一个极端例子,假设客户端和服务端相距1300公里,粗略计算命令传输时间为13毫秒,而命令执行时间只有微秒级,所以如果想要做批量操作而没有使用pipeline这样的功能,那redis的使用效率就不会很高。

客户端实现(jedis)
假设需要执行hset命令1万次,key也有1万个,这样的操作是无法使用hmset来完成的,因为hmset是只针对一个key。
我们先使用for循环进行批量命令操作,最终执行时间为50s,显然对于这样的时间是没办法接受的。

我们换成使用pipeline实现,每次执行100个命令,执行100次pipeline操作,最终时间只需要0.7秒,速度大大提升。

与原生M操作
与原生M操作对比,M操作是一个原子操作,只需要执行和计算一次,而pipeline是将命令进行打包,传送到redis时,则会拆分成子命令,结果会按顺序返回。


使用建议
- 注意每次pipeline携带数据量(数据量过大需合理拆分次数)
- pipeline每次只能作用在一个Redis节点上
- 明确M操作与pipeline区别
发布订阅
角色
角色主要有发布者(publisher)、订阅者(subscriber)、频道(channel)
发布者会发布消息到频道上,订阅者通过订阅频道来获取消息。
类似一些新闻APP(微信公众号),只要订阅了某些频道,这些频道有新消息发布订阅者就能收到消息。
模型
模型如图所示(类似生产者与消费者模型),对于订阅者而言其实也是个客户端,订阅者是可以订阅多个频道的,有个问题就是假如发布者已经发布了一条消息到频道中,但是一个新的订阅者是收不到之前已经发送过的消息的,使用时一定要注意这种场景,就是说redis并没有提供消息堆积的功能,所以无法获取历史消息。

相关API
发布消息:publish channel message

订阅频道:subscribe [channel]
返回信息:订阅了哪个频道,收到消息详细信息

取消订阅:unsubscribe [channel]

其他API,例如第一个命令根据pattern去匹配订阅,如: v*,匹配v开头的频道

消息队列
发布订阅是频道发送一条消息,订阅该频道的订阅者都能收到消息。而消息队列是抢模式,最终只有一个订阅者能抢到消息进行消费。
当然redis本身没有提供消息队列这样的功能,我们可以使用list实现,使用阻塞去拉取...
具体根据场景选择相应的模式,就是要搞清楚你的消费者是都需要收到还是只有一个收到。

Bitmap
位图
每个字符串有对应的二进制,二进制每个数字代表位,即bit
bitmap就是可以用来对位进行操作

例如获取hello对应的value即big,我们可以获取每一位二进制数
网友评论