Redis瑞士军刀:慢查询,Pipeline和发布订阅

1.慢查询

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_tc发布的消息

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

时间: 2024-10-08 10:45:42

Redis瑞士军刀:慢查询,Pipeline和发布订阅的相关文章

Redis 学习之持久化机制、发布订阅、虚拟内存

该问使用centos6.5 64位  redis3.2.8 一.持久化机制 Redis是一个支持持久化的内存数据库,redis会经常将内存中的数据同步到硬盘上来保证数据持久化,从而避免服务器宕机数据丢失问题,或者减少服务器内存消耗提高性能. 持久化方式: 1.Snapshotting:快照,redis默认持久化方式,这种方式是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb.可以通过配置设置自动做快照持久化的方式.我们可以配置redis在n秒内如果超过m个key被修改

Redis研究(十六)—发布/订阅模式

在上一篇中我们写了Redis的任务队列. 除了实现任务队列外,Redis还提供了一组命令可以让开发者实现"发布/订阅"(publish/subscribe)模式."发布/订阅"模式同样可以实现进程间的消息传递,其原理是这样的: "发布/订阅"模式中包含两种角色,分别是发布者和订阅者.订阅者可以订阅一个或若干个频道(channel),而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都会收到此消息. 发布者发布消息的命令是PUBLISH,用法

Redis发布订阅机制

原文:Redis发布订阅机制 1. 什么是Redis Redis是一个开源的内存数据库,它以键值对的形式存储数据.由于数据存储在内存中,因此Redis的速度很快,但是每次重启Redis服务时,其中的数据也会丢失,因此,Redis也提供了持久化存储机制,将数据以某种形式保存在文件中,每次重启时,可以自动从文件加载数据到内存当中.  Redis的架构包括两个部分:Redis Client和Redis Server.Redis客户端负责向服务器端发送请求并接受来自服务器端的响应.服务器端负责处理客户端

redis的发布订阅模式

概要 redis的每个server实例都维护着一个保存服务器状态的redisServer结构 struct redisServer { /* Pubsub */ // 字典,键为频道,值为链表 // 链表中保存了所有订阅某个频道的客户端 // 新客户端总是被添加到链表的表尾 dict *pubsub_channels;  /* Map channels to list of subscribed clients */ // 这个链表记录了客户端订阅的所有模式的名字 list *pubsub_pa

redis pipeset发布订阅

#!/usr/bin/env python # Author:Zhangmingda import redis,time pool = redis.ConnectionPool(host='192.168.11.5',port=6379,db=2) r = redis.Redis(connection_pool=pool) pipe = r.pipeline(transaction=True) pipe.set('age','22') time.sleep(15) pipe.execute()

redis 发布订阅、geo、bitmap、hyperloglog

1.发布订阅 简介 发布订阅类似于广播功能.redis发布订阅包括 发布者.订阅者.Channel 命令 命令 作用 时间复杂度 subscribe channel 订阅一个频道 O(n) unsubscribe channel ... 退订一个/多个频道 O(n) publish channel msg 将信息发送到指定的频道 O(n+m),n 是频道 channel 的订阅者数量, M 是使用模式订阅(subscribed patterns)的客户端的数量 pubsub CHANNELS 查

我在生产项目里是如何使用Redis发布订阅的?(二)Java版代码实现(含源码)

上篇文章讲了在实际项目里的哪些业务场景用到Redis发布订阅,这篇文章就讲一下,在Java中如何实现的. 图解代码结构 发布订阅的理论以及使用场景大家都已经有了大致了解了,但是怎么用代码实现发布订阅呢?在这里给大家分享一下实现方式. 我们以上篇文章的第三种使用场景为例,先来看一下整体实现类图吧. 解释一下,这里我们首先定义一个统一接口`ICacheUpdate`,只有一个`update`方法,我们令`Service`层实现这个方法,执行具体的更新操作. 我们再来看`RedisMsgPubSub`

Redis05——Redis高级运用(管道连接,发布订阅,布隆过滤器)

Redis高级运用 一.管道连接redis(一次发送多个命令,节省往返时间) 1.安装nc yum install nc -y 2.通过nc连接redis nc localhost 6379 3.通过echo向nc发送指令 echo -e "set k2 99\nincr k2\n get k2" |nc localhost 6379 二.发布订阅(pub/Sub) publish channel message subscribe channel 三.事务(transactions)

python之上下文管理、redis的发布订阅

使用with打开文件的方式,是调用了上下文管理的功能 1 #打开文件的两种方法: 2 3 f = open('a.txt','r') 4 5 with open('a.txt','r') as f 6 7 实现使用with关闭socket 8 import contextlib 9 import socket 10 11 @contextlib.contextmanage 12 def Sock(ip,port): 13 socket = socket.socket() 14 socket.bi