Redis消息队列与客户端编程
Redis消息队列与客户端编程文章目录Redis消息队列与客户端编程消息队列生产者/消费者模式发布者/订阅者模式shell脚本访问Redis图形工具连接Redis程序连接Redispycharm连接redis设置和获取值使用字符串操作使用列表操作使用哈希表操作消息队列消息队列把要传输的数据放在队列中从而实现应用之间的数据交换常用功能可以实现多个应用系统之间的解耦异步削峰/限流等常用的消息队列应用:Kafka,RabbitMQ,Redis消息队列分为两种生产者/消费者模式Producer/Consumer发布者/订阅者模式Publisher/Subscriber生产者/消费者模式生产者消费者模式下多个消费者同时监听一个频道redis用队列实现但是生产者产生的一个消息只能被最先抢到消息的一个消费者消费一次队列中的消息由可以多个生产者写入也可以有不同的消费者取出进行消费处理此模式应用广泛思来想去只有 List 和 Streams 两种数据类型可以实现消息队列的这些需求当然Redis 还提供了发布、订阅(pub/sub) 模式。List 实现消息队列Redis 列表是简单的字符串列表按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。所以常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表另一个线程从这个列表中轮询数据进行处理。挑几个弹入、弹出的命令就可以组合出很多姿势LPUSH、RPOP 左进右出RPUSH、LPOP 右进左出案例# 生产者生成消息[rootlocalhost ~]# redis-cli127.0.0.1:6379LPUSH haizeiwang jishu1(integer)1127.0.0.1:6379LPUSH haizeiwang jishu2(integer)2127.0.0.1:6379LPUSH haizeiwang jishu3(integer)3127.0.0.1:6379LPUSH haizeiwang jishu4(integer)4127.0.0.1:6379LPUSH haizeiwang jishu5(integer)5# 获取所有消息127.0.0.1:6379LRANGE haizeiwang0-11)jishu52)jishu43)jishu34)jishu25)jishu1# 消费者消费消息127.0.0.1:6379RPOP haizeiwang#基于实现消息队列的先进先出原则从管道的右侧消费jishu1127.0.0.1:6379RPOP haizeiwangjishu2127.0.0.1:6379RPOP haizeiwangjishu3127.0.0.1:6379RPOP haizeiwangjishu4127.0.0.1:6379RPOP haizeiwangjishu5127.0.0.1:6379RPOP haizeiwang(nil)# 验证队列消息消费全部消费完成127.0.0.1:6379LRANGE haizeiwang0-1(empty list orset)即时消费问题通过 LPUSHRPOP 这样的方式会存在一个性能风险点就是消费者如果想要及时的处理数据就要在程序中写个类似 while(true) 这样的逻辑不停的去调用 RPOP 或 LPOP 命令这就会给消费者程序带来些不必要的性能损失。所以Redis 还提供了 BLPOP、BRPOP 这种阻塞式读取的命令(带 B-Bloking的都是阻塞式)客户端在没有读到队列数据时自动阻塞直到有新的数据写入队列再开始读取新数据。这种方式就节省了不必要的 CPU 开销。LPUSH、BRPOP 左进右阻塞出RPUSH、BLPOP 右进左阻塞出# 生产者生成消息127.0.0.1:6379LPUSH haizeiwang jishu1 jishu2 jishu3 jishu4 jishu5(integer)5# 获取所有消息127.0.0.1:6379LRANGE haizeiwang0-11)jishu52)jishu43)jishu34)jishu25)jishu1# 消费者消费消息127.0.0.1:6379BRPOP haizeiwang101)haizeiwang2)jishu1127.0.0.1:6379BRPOP haizeiwang101)haizeiwang2)jishu2127.0.0.1:6379BRPOP haizeiwang101)haizeiwang2)jishu3127.0.0.1:6379BRPOP haizeiwang101)haizeiwang2)jishu4127.0.0.1:6379BRPOP haizeiwang101)haizeiwang2)jishu5# 消费的时候已经没有消息了10秒内再开一个窗口使用命令LPUSH haizeiwang jishu6产生新消息127.0.0.1:6379BRPOP haizeiwang10#如果将超时时间设置为 0 时即可无限等待直到弹出消息1)haizeiwang2)jishu6(2.73s)127.0.0.1:6379发布者/订阅者模式在发布者订阅者Publisher/Subscriber模式下发布者Publisher将消息发布到指定的频道channel事先监听此channel的一个或多个订阅者Subscriber都会收到相同的消息。即一个消息可以由多个订阅者获取到对于社交应用中的群聊、群发、群公告等场景适用于此模式案例# 订阅者订阅频道#窗口A[rootlocalhost ~]# redis-cli127.0.0.1:6379SUBSCRIBE douluodalu#订阅者事先订阅指定的频道之后发布的消息才能收到 Reading messages...(press Ctrl-C to quit)1)subscribe2)douluodalu3)(integer)1#窗口B127.0.0.1:6379SUBSCRIBE douluodalu haizeiwang#订阅多个频道Reading messages...(press Ctrl-C to quit)1)subscribe2)douluodalu3)(integer)11)subscribe2)haizeiwang3)(integer)2# 发布者发布消息#窗口C127.0.0.1:6379PUBLISH douluodalu fuhuoba,wodeairen(integer)2#订阅者个数2个127.0.0.1:6379PUBLISH haizeiwang 5danglufei(integer)1# 各个订阅者都能收到消息#窗口A[rootlocalhost ~]# redis-cli127.0.0.1:6379SUBSCRIBE douluodalu Reading messages...(press Ctrl-C to quit)1)subscribe2)douluodalu3)(integer)11)message2)douluodalu3)fuhuoba,wodeairen#窗口B[rootlocalhost ~]# redis-cli127.0.0.1:6379SUBSCRIBE douluodalu haizeiwang Reading messages...(press Ctrl-C to quit)1)subscribe2)douluodalu3)(integer)11)subscribe2)haizeiwang3)(integer)21)message2)douluodalu3)fuhuoba,wodeairen1)message2)haizeiwang3)5danglufei# 订阅所有频道127.0.0.1:6379PSUBSCRIBE *# 订阅匹配的频道127.0.0.1:6379PSUBSCRIBE douluo*shell脚本访问Redis脚本内容write_redis.sh#!/bin/bash# Redis 连接参数可根据需要修改REDIS_HOST127.0.0.1REDIS_PORT6379REDIS_DB0# 写入100个键值对foriin{0..99};doKEYkey:$iVALUE$iredis-cli -h$REDIS_HOST-p$REDIS_PORT-n$REDIS_DBSET$KEY$VALUEdoneecho已成功写入100条数据到 Redis。给脚本添加执行权限[rootlocalhost ~]# chmod x write_redis.sh运行脚本[rootlocalhost ~]# ./write_redis.shOK......OK 已成功写入100条数据到 Redis。[rootlocalhost ~]##验证结果127.0.0.1:6379info keyspace# Keyspacedb0:keys100,expires0,avg_ttl0127.0.0.1:6379keys key:*可选增强功能带密码认证如果 Redis 设置了密码加上-a your_password 注意安全性或使用–askpass 。批量管道操作更快如需更高性能可使用redis-cli --pipe批量导入适合大量数据。图形工具连接RedisRedis Desktop Manager又名RDM它是一款用于WindowsLinux和MacOS的快速开源Redis数据库管理应用程序能够为用户提供一系列功能选择以及操作设定以便于用户直接对需要管理的Redis数据库进行建设性操作以树形的方式来罗列出密匙以及CRUD密钥可节约用户的很多宝贵时间此工具支持识别shell命令管理员能够根据自己的需要添加shel以此让程序系统执行对应的命令操作它为用户提供中文显示界面同时还提供了通俗易懂的用户界面无论是新手用户还可以经验十足的用户都可以非常轻松的上手。Github地址https://github.com/qishibo/AnotherRedisDesktopManager需要提前在redis服务器上配置redis密码和关闭防火墙更改bind地址[rootlocalhost ~]# systemctl stop firewalld[rootlocalhost ~]# vim /etc/redis.conf69bind0.0.0.0[rootlocalhost ~]# systemctl restart redis127.0.0.1:6379CONFIG SET requirepass123456OK程序连接RedisRedis支持多种开发语言访问https://redis.io/docs/latest/develop/clients/基本语句pythonpython提供了多种开发库都可以支持连接访问Redis下面选择使用redis-py库连接redis# redis-py 使用手册https://redis.io/docs/latest/develop/clients/redis-py/pycharm连接redispipinstallredisimportredis rredis.Redis(host192.168.108.172,port6379,password123456,db0)print(r)解释importredis导入redis模块这是 Python 操作 Redis 的官方客户端库需提前安装pip installredis 。 rredis.Redis(host192.168.108.172,port6379,password123456,db0)创建一个 Redis 客户端对象r 用于与远程 Redis 服务器通信host: Redis 服务器 IP 地址这里是局域网中的192.168.108.172 port: Redis 默认端口6379password: 认证密码’123456’ 说明 Redis 配置了requirepass 123456 db: 使用第0号数据库Redis 默认有 16 个逻辑数据库编号 0~15print®打印 Redis 客户端对象的描述信息这只是对象的内部表示用于调试确认连接配置是否正确。接收 set 操作的返回值importredisrredis.Redis(host192.168.108.172,port6379,password123456,db0)print(r)# 接收 set 操作的返回值resultr.set(color1,red)print(result)# 输出 True或 OK取决于 redis-py 版本注意文件不要为redis,会和redis模块名称冲突解释:resultr.set(color1,red)调用set() 方法向 Redis 中设置一个字符串类型的键值对键key‘color1’值value‘red’这相当于在 Redis CLI 中执行SET color1 redprint(result)r.set()的返回值说明redis-py 版本r.set(…) 成功时的返回值4.0.0 及以上True 布尔值✅当前主流版本3.x 及更早b’OK’ 字节串自redis-py 4.0起为了更符合 Python 习惯成功操作统一返回True 失败则抛出异常如连接错误、认证失败等。设置和获取值可以使用set和get方法来存储和检索数据#存储变量r.set(color1,red)#获取变量值valuer.get(color1)print(value)使用字符串操作redis-py提供了多种字符串操作方法如incr增加decr减少append追加等。r.set(‘int1’,10)#自增restultr.incr(int1)#自减restultr.decr(int1)print(restult)使用列表操作Redis的列表是一个简单的字符串列表可以进行lpush从左边插入、rpush从右边插入、lpop从左边弹出、rpop从右边弹出等操作。#列表r.lpush(mylist,nihao)r.lpush(mylist,laogao)print(r.lrange(mylist,0,-1))注释r.lpush(‘mylist’,‘nihao’)使用 LPUSH 命令将字符串 ‘nihao’ 从左侧头部推入名为 mylist 的列表。如果 mylist 不存在Redis 会自动创建它。执行后mylist 内容为[‘nihao’]r.lpush(‘mylist’,‘laogao’)再次使用 LPUSH将 ‘laogao’ 插入到列表最左边。列表是“头进”所以新元素在前。此时 mylist 内容变为[‘laogao’, ‘nihao’]print(r.lrange(‘mylist’,0,-1))使用 LRANGE 命令获取列表 mylist 中从索引 0 到 -1即全部元素的内容。在 Redis 中-1 表示最后一个元素0 是第一个。r.lrange(…) 返回的是字节串bytes组成的列表因为 Redis 存储的是二进制安全的字符串。小知识Redis 列表是“左进右出”还是“右进左出”LPUSH 从左边插入→新元素在头部RPUSH 从右边插入→新元素在尾部列表索引0是最左边最新插入的 LPUSH 元素-1是最右边最早插入的[b’laogao’, b’nihao’]注意每个字符串前面有 b’…表示这是 bytes 类型不是普通字符串str。使用哈希表操作Redis的哈希表是一个字符串字段和字符串值之间的映射表可以进行hset设置字段、hget获取字段、hgetall获取所有字段和值等操作。#哈希r.hset(student,name,lisi)r.hset(student,age,18)print(r.hget(student,name))print(r.hget(student,age))print(r.hgetall(student))r.hset(student,name,lisi)在名为’student’的**哈希表Hash**中设置字段field‘name’的值为’lisi’ 。相当于执行 Redis 命令HSET student name lisir.hset(‘student’,‘age’,‘18’)在同一个哈希表’student’中再设置字段’age’的值为’18’ 。注意Redis 中所有值都是字符串即使看起来像数字如’18’ 存储时也是字符串类型。print(r.hget(‘student’,‘name’))获取哈希表’student’中字段’name’的值。返回值是bytes 类型因为 redis-py 默认返回字节。输出b’lisi’print(r.hget(‘student’,‘age’))获取’age’字段的值。输出b’18’print(r.hgetall(‘student’))获取’student’哈希表中所有字段和值。返回一个字典dict但键和值都是 bytes 类型。