1.1 慢查询的生命周期
步骤一: client 通过网络向 Redis 发送一条命令
步骤二: 由于 Redis 是单线程应用, 可以把 Redis 想像成一个队列, client 执行的所有命令都在排队等着 server 端执行
步骤三: Redis 服务端按顺序执行命令
步骤四: server 端把命令结果通过网络返回给 client
说明:
慢查询发生在命令执行过程中, 不包含网络延迟时间及排除等待执行的时间
客户端超时不一定慢查询, 但慢查询是客户端超时的一个可能因素
1.2 慢查询的配置项
slowlog-max-len 慢查询队列的长度
slowlog-log-slower-than 慢查询阈值 (单位: 微秒), 执行时间超过阀值的命令会被加入慢查询命令
如果设置为 0, 则会记录所有命令, 通常在需要记录每条命令的执行时间时使用
如果设置为小于 0, 则不记录任何命令
slowlog list 慢查询记录
说明:
慢查询是一个先进先出的队列, 如果一条命令在执行过程中被列入慢查询范围内, 就会被放入一个队列, 这个队列是基于 Redis 的列表来实现
, 而且这个队列是固定长度的, 当队列的长度达到固定长度时, 最先被放入队列就会被 pop 出去
慢查询队列保存在内存之中, 不会做持久化, 当 Redis 重启之后就会消失
1.3 慢查询配置方法
1.3.1 修改配置文件重启
修改 / etc/Redis.conf 配置文件, 配置慢查询
修改配置方式应该在第一次配置 Redis 中时配置完成, 生产后不建议修改配置文件
1.3.2 动态配置
- 127.0.0.1:6379> config get slowlog-max-len
- 1) "slowlog-max-len"
- 2) "128"
- 127.0.0.1:6379> config get slowlog-log-slower-than
- 1) "slowlog-log-slower-than"
- 2) "10000"
- 127.0.0.1:6379> config set slowlog-max-len 1000
- OK
- 127.0.0.1:6379> config get slowlog-max-len
- 1) "slowlog-max-len"
- 2) "1000"
- 127.0.0.1:6379> config set slowlog-log-slower-than 1000
- OK
- 127.0.0.1:6379> config get slowlog-log-slower-than
- 1) "slowlog-log-slower-than"
- 2) "1000"
1.4 慢查询命令
slowlog get [n] 获取慢查询队列
slowlog len 获取慢查询队列长度
slowlog reset 清空慢查询队列
1.5 Redis 慢查询运维经验
slowlog-max-len 不要设置过小, 通常设置 1000 左右
slowlog-log-slower-than 不要设置过大, 默认 10ms, 通常设置 1ms
理解命令生命周期
可以通过 slowlog get 等命令定期将慢查询命令持久化到其他数据源, 这样就可以查到很多历史的慢查询操作命令
在生产环境中, 不管 slowlog-max-len 设置多大, 当慢查询命令逐步增多时, 最开始的慢查询命令会被丢掉
当需要查询历史数据时, 这些慢查询命令都是非常关键的
可以使用开源软件来实现这些功能, 对于分析解决 Redis 问题是非常有帮助的
2.Pipeline
2.1 Pipeline 的概念
一次网络命令通信模型:
client 通过网络传输命令到 server 端
server 端通过计算得到命令执行结果
server 端把命令执行结果给 client
此时:
一次网络命令通信时间 = 1 次网络时间 + 1 次命令时间
此时如果有多条命令呢, 那就只能一条一条的输入命令执行了
n 次时间 = n 次网络时间 + n 次命令时间
Redis 执行命令的时间很快, 但是网络传输却可能有很大延迟,
pipeline 就是把一批命令进行打包, 然后传输给 server 端进行批量计算, 然后按顺序将执行结果返回给 client 端
使用 Pipeline 模型进行 n 次网络通信需要的时间
1 次 pipeline(n 条命令) = 1 次网络时间 + n 次命令时间
2.2 例子
- import Redis
- import time
- client = Redis.StrictRedis(host='192.168.81.100',port=6379)
- start_time = time.time()
- for i in range(10000):
- client.hset('hashkey','field%d' % i,'value%d' % i)
- ctime = time.time()
- print(client.hlen('hashkey'))
- print(ctime - start_time)
程序执行结果:
- 10000
- 2.0011684894561768
在上面的例子里, 直接向 Redis 中写入 10000 条 hash 记录, 需要的时间为 2.00 秒
使用 pipeline 的方式向 Redis 中写入 1 万条 hash 记录
- import Redis
- import time
- client = Redis.StrictRedis(host='192.168.81.100',port=6379)
- start_time = time.time()
- for i in range(100):
- pipeline = client.pipeline()
- j = i * 100
- while j <(i+ 1) * 100:
- pipeline.hset('hashkey1','field%d' % j * 100,'value%d' % i)
- j += 1
- pipeline.execute()
- ctime = time.time()
- print(client.hlen('hashkey1'))
- print(ctime - start_time)
程序执行结果:
- 10000
- 0.3175079822540283
可以看到使用 Pipeline 方式每次向 Redis 服务端发送 100 条命令, 发送 100 次所需要的时间仅为 0.31 秒, 可以看到使用 Pipeline 可以节省网络传输时间
2.3 Pipeline 使用建议
首先要注意每次 pipeline 携带数据量不能太大
pipeline 可以提高 Redis 批量处理的并发的能力, 但是并不能无节制的使用
如果批量执行的命令数量过大, 则很容易对网络及客户端造成很大影响, 此时可以把命令分割, 每次发送少量的命令到服务端执行
pipeline 每次只能作用在一个 Redis 节点上
3. 发布订阅
3.1 发布订阅中的角色
发布者 (publisher)
订阅者 (subscriber)
频道 (channel)
3.2 发布订阅的模型
Redis server 就相当于频道
发布者是一个 Redis-cli, 通过 Redis server 发布消息
订阅者也是于一个 Redis-cli, 如果订阅了这个频道, 就可以通过 Redis server 获取消息
说明:
发布订阅就是一个生产者消费者模型
每个订阅者可以订阅多个频道
发布者发布消息后, 订阅者就可以收到不同频道的消息
订阅者不可以接收未订阅频道的消息
订阅者订阅某个频道后, Redis 无法做消息的堆积, 不能接收频道被订阅之前发布的消息
3.3 发布订阅的命令
publish channel message 发布消息
subscribe [channel] 订阅频道
unsubscribe [channel] 取消订阅
psubscribe [pattern...] 订阅指定模式的频道
punsubscribe [pattern...] 退订指定模式的频道
pubsub channels 列出至少有一个订阅者的频道
pubsub numsub [channel...] 列表给定频道的订阅者数量
pubsub numpat 列表被订阅模式的数量
例子:
打开一个终端 1
- 127.0.0.1:6379> subscribe sohu_tv # 订阅 sohu_tv 频道
- Reading messages... (press Ctrl-C to quit)
- 1) "subscribe"
- 2) "sohu_tv"
- 3) (integer) 1
再次打开一个终端 2
- 127.0.0.1:6379> publish sohu_tv 'hello python' # sohu_tv 频道发布消息
- (integer) 1
- 127.0.0.1:6379> publish sohu_tv 'hello world' # sohu_tv 频道发布消息
- (integer) 3
可以看到终端 1 中已经接收到 sohu_tv 发布的消息
- 127.0.0.1:6379> subscribe sohu_tv
- Reading messages... (press Ctrl-C to quit)
- 1) "subscribe"
- 2) "sohu_tv"
- 3) (integer) 1
- 1) "message"
- 2) "sohu_tv"
- 3) "hello python"
- 1) "message"
- 2) "sohu_tv"
- 3) "hello world"
打开终端 3, 取消订阅 sohu_tc 频道
- 127.0.0.1:6379> unsubscribe sohu_tv
- 1) "unsubscribe"
- 2) "sohu_tv"
- 3) (integer) 0
3.4 发布订阅与消息队列
Redis server 维护一个队列
消息发布者, 相当于一个 Redis-cli, 通过 Redis server 发布消息
消息订阅者就相当于一个 Redis-cli, 所有的消息订阅者通过 Redis server 抢消息发布者发布的消息
来源: https://www.cnblogs.com/renpingsheng/p/9779926.html