步骤一:client经过网络向Redis发送一条命令 步骤二:因为Redis是单线程应用,能够把Redis想像成一个队列,client执行的全部命令都在排队等着server端执行 步骤三:Redis服务端按顺序执行命令 步骤四:server端把命令结果经过网络返回给client
说明:python
慢查询发生在命令执行过程当中,不包含网络延迟时间及排除等待执行的时间 客户端超时不必定慢查询,但慢查询是客户端超时的一个可能因素
slowlog-max-len 慢查询队列的长度 slowlog-log-slower-than 慢查询阈值(单位:微秒),执行时间超过阀值的命令会被加入慢查询命令 若是设置为0,则会记录全部命令,一般在须要记录每条命令的执行时间时使用 若是设置为小于0,则不记录任何命令 slowlog list 慢查询记录
说明:redis
慢查询是一个先进先出的队列,若是一条命令在执行过程当中被列入慢查询范围内,就会被放入一个队列,这个队列是基于Redis的列表来实现 ,并且这个队列是固定长度的,当队列的长度达到固定长度时,最早被放入队列就会被pop出去 慢查询队列保存在内存之中,不会作持久化,当Redis重启以后就会消失
修改/etc/redis.conf配置文件,配置慢查询 修改配置方式应该在第一次配置Redis中时配置完成,生产后不建议修改配置文件
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"
slowlog get [n] 获取慢查询队列 slowlog len 获取慢查询队列长度 slowlog reset 清空慢查询队列
slowlog-max-len不要设置太小,一般设置1000左右 slowlog-log-slower-than不要设置过大,默认10ms,一般设置1ms 理解命令生命周期 能够经过slowlog get等命令按期将慢查询命令持久化到其余数据源,这样就能够查到不少历史的慢查询操做命令 在生产环境中,无论slowlog-max-len设置多大,当慢查询命令逐步增多时,最开始的慢查询命令会被丢掉 当须要查询历史数据时,这些慢查询命令都是很是关键的 能够使用开源软件来实现这些功能,对于分析解决Redis问题是很是有帮助的
一次网络命令通讯模型:网络
client经过网络传输命令到server端 server端经过计算获得命令执行结果 server端把命令执行结果给client
此时:并发
一次网络命令通讯时间=1次网络时间 + 1次命令时间
此时若是有多条命令呢,那就只能一条一条的输入命令执行了运维
n次时间 = n次网络时间 + n次命令时间
Redis执行命令的时间很快,可是网络传输却可能有很大延迟,ui
pipeline就是把一批命令进行打包,而后传输给server端进行批量计算,而后按顺序将执行结果返回给client端线程
使用Pipeline模型进行n次网络通讯须要的时间code
1次pipeline(n条命令) = 1次网络时间 + n次命令时间
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)
程序执行结果:server
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能够节省网络传输时间
首先要注意每次pipeline携带数据量不能太大 pipeline能够提升Redis批量处理的并发的能力,可是并不能无节制的使用 若是批量执行的命令数量过大,则很容易对网络及客户端形成很大影响,此时能够把命令分割,每次发送少许的命令到服务端执行 pipeline每次只能做用在一个Redis节点上
发布者(publisher) 订阅者(subscriber) 频道(channel)
Redis server就至关于频道 发布者是一个redis-cli,经过redis server发布消息 订阅者也是于一个redis-cli,若是订阅了这个频道,就能够经过redis server获取消息
说明:
发布订阅就是一个生产者消费者模型 每一个订阅者能够订阅多个频道 发布者发布消息后,订阅者就能够收到不一样频道的消息 订阅者不能够接收未订阅频道的消息 订阅者订阅某个频道后,Redis没法作消息的堆积,不能接收频道被订阅以前发布的消息
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
redis server维护一个队列 消息发布者,至关于一个redis-cli,经过redis server发布消息 消息订阅者就至关于一个redis-cli,全部的消息订阅者经过redis server抢消息发布者发布的消息