【redis】python操作与频道发布与订阅

前言

本文讲述如何用python连接使用redis和利用redis进行频道的订阅和消息发布,默认读者对于redis的基本概念和如何创建redis服务已经知晓。

python操作redis

python操作redis主要包含几步:

  • 连接redis数据库
  • 数据的增删查改

    连接redis数据库

  • 直接连接
    redis提供了RedisStrictRedis两种直连redis的方式,前者是为了兼容2.x版本,一般我们都用StrictRedis

    import redis
    redis_conn = redis.StrictRedis(host='127.0.0.1',port=6379,db=0,password=None)  # 上述参数都是默认值,根据需要修改
  • ConnectionPool连接
    实际上每一个StrictRedis直连都会创建一个ConnectionPool,并且在连接断开时销毁,我们可以将这部分内容手动创建,连接池会预先创建多个连接,当进行redis操作时,直接获取已经创建好的连接进行操作。完成后,不会释放这个连接,而是让其返回连接池,用于后续redis操作,这样在高并发的连接中就能提高性能。
    import redis
    
    conn_pool = redis.ConnectionPool(host='127.0.0.1',port=6379,db=0,password=None)
    redis_conn = redis.StrictRedis(connection_pool=conn_pool)

    增删查改

既然是数据库,核心就是这几个操作,redis中采用键值对的方式存储数据,可以想象成一个字典。

  • 添加数据&修改数据
    包含setmset方法,后者是前者的多重,用于一次设置多个值。下面用具体代码展示;

    • set(name, value, ex=None, px=None, nx=False, xx=False)

      redis_conn.set('data',5)
      redis_conn.set('data2',6,ex=10)  # 设置10秒超时,超时后自动删除该数据,ex单位秒,px单位毫秒
      redis_conn.set('data',9,nx=True)  # 当`data`不存在时才创建
      redis_conn.set('data',10,xx=True)  # 当`data`存在时才创建
      data_dict = {
          'data3':11,
          'data4':12
      }
      redis_conn.mset(data_dict)  # 一次设置多个键值

      一般来说我们通常只用第一条,其他的几个也了解一下即可

      除此之外,还有一个用于在数据后面添加新数据的方法append,当数据不存在时新建,若存在,则添加到已有数据尾部,返回值是数据的长度

      length = redis_conn.append('data', '666')  # data:b'10666',length:5
  • 查找数据
    包含getmget方法,后者用于一次获取多个。注意返回的值是bytes对象。

    redis_conn.get('data')  # b'10' 
    query_list = ['data','data2','data3','data4']
    redis_conn.mget(query_list)  # [b'10', None, b'11', b'12']
  • 删除数据
    delete方法,允许删除单个或删除多个(根据键)
    redis_conn.delete('data')
    redis_conn.delete('data2','data3')
    上面主要是string类型数据在redis中的操作,redis还支持List,Hash,Set等多种类型,具体可以看这篇:Python对Redis增删改查

频道发布与订阅

redis允许发布频道,通过频道传达信息,其他对象可以订阅该频道以获取相应的信息,直观一点的理解就是server,clientsocket通信。主要分为发布端订阅端

发布端

例如我们用redis创建一个对象,通过publish方法发布一个频道,同时往该频道中输送信息:

import redis

pool = redis.ConnectionPool(host='127.0.0.1',port=6379, db=0,password='chaopeng')
r = redis.StrictRedis(connection_pool=pool)

while True:
    msg = input("publish: >>")
    r.publish(channel='cctv', message=msg)
    if msg == "exit":
        print("结束发布")
        break

启动效果:

订阅端

订阅端要想获取发布的信息,需要订阅相应频道,相当于client监听了指定端口:

import redis

pool = redis.ConnectionPool(host='127.0.0.1',port=6379, db=0,password='chaopeng')
redis_conn = redis.StrictRedis(connection_pool=pool)
p = redis_conn.pubsub()
p.subscribe("cctv")
for item in p.listen():
    print("正在监听频道:{}".format(item['channel'].decode()) )
    if item['type'] == 'message':
        data = item['data'].decode()
        print("频道 {} 发来新消息:{}" .format(item['channel'].decode(), data))
        if data == 'exit':
            print(item['channel'].decode(), '发布结束')
            break
p.unsubscribe('cctv')
print("取消订阅")

启动效果:

监听过程中主要传输的item具体包含下面的信息:

  • type: subscribe, unsubscribe, psubscribe, punsubscribe, message, pmessage之一,用于识别监听到的数据类型,一般第一次订阅是subscribe,后面都是message

    {‘type’: ‘subscribe’, ‘pattern’: None, ‘channel’: b’cctv’, ‘data’: 1}

  • channel: 发布消息的频道

  • pattern: 用于匹配发布消息的频道模式,一般而言,我们用不到这个,都是None
  • data: 具体的传输信息

    总结

redis是一个高速的内存数据库,在制作小有规模的项目时难免会遇到对于数据的临时存储,redis是一个很好的解决方案。在应用多进程的时候,可以很好地利用发布与订阅的机制进行消息的共享。