redis协议格式请参考,http://doc.redisfans.com/topic/protocol.html

这里简单介绍下:

  1. *<参数数量> \r\n
  2. $<参数 的字节数量> \r\n
  3. <参数 的数据> \r\n
  4. $<参数 N 的字节数量> \r\n
  5. <参数 N 的数据> \r\n

发送给redis服务器时的数据要按照redis要求的协议格式发送,只有这样redis服务器才能成功解析。

首先根据协议格式写一个封包方法,代码如下:

  1. def format_command(self, commands):
  2. length = len(commands)
  3. command = "*{}\r\n".format(length)
  4. for v in commands:
  5. bytes = v.encode("utf-8")
  6. bytes_length = len(bytes)
  7. sub_command = "${}\r\n".format(bytes_length) + "{}\r\n".format(v)
  8. command += sub_command
  9. return command

看到format_command函数中的“*”和“$”符号了么。其实就是根据commands列表中的数据然后按照redis协议格式封装起来的。

弄懂了如何安装redis协议封装数据之后,就可以把数据发送到redis服务器了。

asyncio的官方demo可参考:

https://docs.python.org/3/library/asyncio-stream.html#tcp-echo-client-using-streams

下面就是完整的代码,无其他依赖,顺利执行之后,可以通过redis-cli命令行查看是否设置成功。

  1.  
  1. class AsyncRedis:
  2.  
  3. def __init__(self, host, port, loop):
  4. self.host = host
  5. self.port = port
  6. self.loop = loop
  7. self.separator = "\r\n".encode()
  8.  
  9. async def connect(self):
  10. reader, writer = await asyncio.open_connection(self.host, self.port, loop=self.loop)
  11. self.reader = reader
  12. self.writer = writer
  13.  
  14. def format_command(self, commands):
  15. length = len(commands)
  16. command = "*{}\r\n".format(length)
  17. for v in commands:
  18. bytes = v.encode("utf-8")
  19. bytes_length = len(bytes)
  20. sub_command = "${}\r\n".format(bytes_length) + "{}\r\n".format(v)
  21. command += sub_command
  22. print(command)
  23. return command
  24.  
  25. def execute_command(self, command):
  26. self.writer.write(command.encode("utf-8"))
  27.  
  28. async def set(self, key, value):
  29. command = self.format_command(["SET", key, value])
  30. self.execute_command(command)
  31. ret, error = await self.wait_ret()
  32. print(ret)
  33. return ret
  34.  
  35. async def hset(self, hash_key, key, value):
  36. command = self.format_command(["HSET", hash_key, key, value])
  37. self.execute_command(command)
  38.  
  39. async def get(self, key):
  40. command = self.format_command(['GET', key])
  41. self.execute_command(command)
  42. ret = await self.wait_ret()
  43. return ret
  44.  
  45. async def wait_ret(self):
  46. ret = await self.reader.readuntil(self.separator)
  47. ret = ret.decode()
  48. mark = ret[0:1]
  49. if mark == "$":
  50. pos = ret.index("\r\n")
  51. ret = ret[1:pos]
  52. ret = await self.reader.read(int(ret))
  53. ret = ret.decode()
  54. return ret, True
  55. elif mark == "+":
  56. pos = ret.index("\r\n")
  57. ret = ret[1:pos]
  58. return ret, True
  59. elif mark == "-":
  60. pos = ret.index("\r\n")
  61. ret = ret[1:pos]
  62. return ret, False
  63.  
  64. async def close(self):
  65. self.writer.close()
  66.  
  67. import asyncio
  68.  
  69. async def NewRedis(loop):
  70. redis = AsyncRedis("127.0.0.1", 6379, loop)
  71. await redis.connect()
  72. # await redis.get("name")
  73. await redis.set("name", "云想衣裳花想容,春风拂槛露华浓。\r\n 若非群玉山头见,会向瑶台月下逢。")
  74. loop = asyncio.get_event_loop()
  75. loop.run_until_complete(NewRedis(loop))
  76. loop.close()

使用asyncio实现redis客户端的更多相关文章

  1. 测试平台系列(80) 封装Redis客户端

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...

  2. StackExchange.Redis客户端读写主从配置,以及哨兵配置。

    今天简单分享一下StackExchange.Redis客户端中配置主从分离以及哨兵的配置. 关于哨兵如果有不了解的朋友,可以看我之前的一篇分享,当然主从复制文章也可以找到.http://www.cnb ...

  3. c#实现redis客户端(一)

    最近项目使用中要改造redis客户端,看了下文档,总结分享一下. 阅读目录: 协议规范 基础通信 状态命令 set.get命令 管道.事务 总结 协议规范 redis允许客户端以TCP方式连接,默认6 ...

  4. 使用StackExchange.Redis客户端进行Redis访问出现的Timeout异常排查

    问题产生 这两天业务系统在redis的使用过程中,当并行客户端数量达到200+之后,产生了大量timeout异常,典型的异常信息如下: Timeout performing HVALS Parser2 ...

  5. Redis客户端之Spring整合Jedis,ShardedJedisPool集群配置

    Jedis设计 Jedis作为推荐的java语言redis客户端,其抽象封装为三部分: 对象池设计:Pool,JedisPool,GenericObjectPool,BasePoolableObjec ...

  6. 从零开始写redis客户端(deerlet-redis-client)之路——第一个纠结很久的问题,restore引发的血案

    引言 正如之前的一篇博文,LZ最近正在从零开始写一个redis的客户端,主要目的是为了更加深入的了解redis,当然了,LZ也希望deerlet客户端有一天能有一席之地.在写的过程当中,LZ遇到了一个 ...

  7. Redis 客户端配置及示例

    一.redis自定义配置节点 <configSections> <section name ="RedisConfig" type="Amy.Toolk ...

  8. Redis客户端Java服务接口封装

    最近在学习Redis并集成到Spring中去,发现Spring的RedisTemplate并不好用,还没有MongoTemplate好用. 而且发现Jedis和ShardedJedis的方法非常多,覆 ...

  9. "Redis客户端连接数一直降不下来"的有关问题解决

    [线上问题] "Redis客户端连接数一直降不下来"的问题解决 前段时间,上线了新的 Redis缓存(Cache)服务,准备替换掉 Memcached. 为什么要将 Memcach ...

随机推荐

  1. mysql 在一个实例运行情况下再搭建一个实例

    配置mysql服务 详细步骤,请参考(http://study.lishiming.net/chapter17.html#mysql), 阿铭只把简单步骤写一下. 根据阿铭提供的地址,假如你已经搭建好 ...

  2. thinkphp5判断移动或pc端访问并调用不同模板

    废话不多说,直接上代码 先修改\thinkphp\library\think\view\driver\Think.php文件 把 public function __construct($config ...

  3. 来了解一下Mysql索引的相关知识:基础概念、性能影响、索引类型、创建原则、注意事项

    索引的基础概念索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录,定位对应的页码:存储引擎使用类似的方式进行数据查询,先去索引当中找到对应的值,然后根据匹配的索引找到对应的数据行 ...

  4. MysqL读写分离的实现-Mysql proxy中间件的使用

    为什么要架设读写分离,这里不做多余的说明,想了解具体原理,请百度或者参考其他帖子.在这里只做大概的配置说明,测试中使用三台服务器 192.168.136.142   主服务器 192.168.136. ...

  5. 浙江省赛 C What Kind of Friends Are You?

    思路:一开始考虑n个朋友可以有c种可能,根据回答的问题,如果是yes那么可以确定一些朋友的范围,将原本不在这个范围内的删除即可:如果是"no",说明这些朋友都应该被删除,那么最后看 ...

  6. LOJ6277~6285 数列分块入门

    Portals 分块需注意的问题 数组大小应为,因为最后一个块可能会超出的范围. 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 数列分块入门 1 给出一个长为的数列, ...

  7. APP性能测试(启动时间)

    #encoding:utf-8 import csv import os import time class App(object): def __init__(self): self.content ...

  8. nginx新的站点的配置

    每一次配置新的站点的时候,要记得重新启动nginx: sudo -s; nginx -s reload; 配置文件,有涉及到 每一个站点都有一个.conf文件. 域名重定向:Gas Mask的软件的使 ...

  9. java I/O框架 (二)文件操作(File)

    1.介绍 java io中最常操作的就是我们电脑中的文件,将这些文件以流的形式本地读写,或者上传到网络上.java中的File类就是对这些存储于磁盘上文件的虚拟映射,这也体现了java面向对象的思想, ...

  10. 笔记︱集成学习Ensemble Learning与树模型、Bagging 和 Boosting

    本杂记摘录自文章<开发 | 为什么说集成学习模型是金融风控新的杀手锏?> 基本内容与分类见上述思维导图. . . 一.机器学习元算法 随机森林:决策树+bagging=随机森林 梯度提升树 ...