使用asyncio实现redis客户端
redis协议格式请参考,http://doc.redisfans.com/topic/protocol.html
这里简单介绍下:
*<参数数量> \r\n
$<参数 的字节数量> \r\n
<参数 的数据> \r\n
$<参数 N 的字节数量> \r\n
<参数 N 的数据> \r\n
发送给redis服务器时的数据要按照redis要求的协议格式发送,只有这样redis服务器才能成功解析。
首先根据协议格式写一个封包方法,代码如下:
def format_command(self, commands):
length = len(commands)
command = "*{}\r\n".format(length)
for v in commands:
bytes = v.encode("utf-8")
bytes_length = len(bytes)
sub_command = "${}\r\n".format(bytes_length) + "{}\r\n".format(v)
command += sub_command
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命令行查看是否设置成功。
class AsyncRedis:
def __init__(self, host, port, loop):
self.host = host
self.port = port
self.loop = loop
self.separator = "\r\n".encode()
async def connect(self):
reader, writer = await asyncio.open_connection(self.host, self.port, loop=self.loop)
self.reader = reader
self.writer = writer
def format_command(self, commands):
length = len(commands)
command = "*{}\r\n".format(length)
for v in commands:
bytes = v.encode("utf-8")
bytes_length = len(bytes)
sub_command = "${}\r\n".format(bytes_length) + "{}\r\n".format(v)
command += sub_command
print(command)
return command
def execute_command(self, command):
self.writer.write(command.encode("utf-8"))
async def set(self, key, value):
command = self.format_command(["SET", key, value])
self.execute_command(command)
ret, error = await self.wait_ret()
print(ret)
return ret
async def hset(self, hash_key, key, value):
command = self.format_command(["HSET", hash_key, key, value])
self.execute_command(command)
async def get(self, key):
command = self.format_command(['GET', key])
self.execute_command(command)
ret = await self.wait_ret()
return ret
async def wait_ret(self):
ret = await self.reader.readuntil(self.separator)
ret = ret.decode()
mark = ret[0:1]
if mark == "$":
pos = ret.index("\r\n")
ret = ret[1:pos]
ret = await self.reader.read(int(ret))
ret = ret.decode()
return ret, True
elif mark == "+":
pos = ret.index("\r\n")
ret = ret[1:pos]
return ret, True
elif mark == "-":
pos = ret.index("\r\n")
ret = ret[1:pos]
return ret, False
async def close(self):
self.writer.close()
import asyncio
async def NewRedis(loop):
redis = AsyncRedis("127.0.0.1", 6379, loop)
await redis.connect()
# await redis.get("name")
await redis.set("name", "云想衣裳花想容,春风拂槛露华浓。\r\n 若非群玉山头见,会向瑶台月下逢。")
loop = asyncio.get_event_loop()
loop.run_until_complete(NewRedis(loop))
loop.close()
使用asyncio实现redis客户端的更多相关文章
- 测试平台系列(80) 封装Redis客户端
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了Redis ...
- StackExchange.Redis客户端读写主从配置,以及哨兵配置。
今天简单分享一下StackExchange.Redis客户端中配置主从分离以及哨兵的配置. 关于哨兵如果有不了解的朋友,可以看我之前的一篇分享,当然主从复制文章也可以找到.http://www.cnb ...
- c#实现redis客户端(一)
最近项目使用中要改造redis客户端,看了下文档,总结分享一下. 阅读目录: 协议规范 基础通信 状态命令 set.get命令 管道.事务 总结 协议规范 redis允许客户端以TCP方式连接,默认6 ...
- 使用StackExchange.Redis客户端进行Redis访问出现的Timeout异常排查
问题产生 这两天业务系统在redis的使用过程中,当并行客户端数量达到200+之后,产生了大量timeout异常,典型的异常信息如下: Timeout performing HVALS Parser2 ...
- Redis客户端之Spring整合Jedis,ShardedJedisPool集群配置
Jedis设计 Jedis作为推荐的java语言redis客户端,其抽象封装为三部分: 对象池设计:Pool,JedisPool,GenericObjectPool,BasePoolableObjec ...
- 从零开始写redis客户端(deerlet-redis-client)之路——第一个纠结很久的问题,restore引发的血案
引言 正如之前的一篇博文,LZ最近正在从零开始写一个redis的客户端,主要目的是为了更加深入的了解redis,当然了,LZ也希望deerlet客户端有一天能有一席之地.在写的过程当中,LZ遇到了一个 ...
- Redis 客户端配置及示例
一.redis自定义配置节点 <configSections> <section name ="RedisConfig" type="Amy.Toolk ...
- Redis客户端Java服务接口封装
最近在学习Redis并集成到Spring中去,发现Spring的RedisTemplate并不好用,还没有MongoTemplate好用. 而且发现Jedis和ShardedJedis的方法非常多,覆 ...
- "Redis客户端连接数一直降不下来"的有关问题解决
[线上问题] "Redis客户端连接数一直降不下来"的问题解决 前段时间,上线了新的 Redis缓存(Cache)服务,准备替换掉 Memcached. 为什么要将 Memcach ...
随机推荐
- 打通MySQL的操作权限
打通MySQL的操作权限 前面已经总结了<XAMPP的配置与使用>,虽然可以直接通过GUI控制面板去启动MySQL服务,但是有些相关的操作则需要在Windows中的CMD命令窗口中去对My ...
- scp的简单记忆方法
scp虽然只有把文见发送到远端和从远端copy文件俩功能,但是常常把俩功能的先写什么给计混了,所以我就用通俗的大白话给总结了下,十分容易记忆,这里给大家分享一下.scp 我们常用的两个功能: (1)把 ...
- GET和POST传送数据的限制
GET 方法 请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的: /test/demo_form.asp?name1=value1&name2=value2 有关 GET ...
- Unicode字符集,各个语言的区间
链接:http://www.cnblogs.com/zl0372/p/unicode.html 链接:http://www.unicode.org/ 链接:https://zh.wikipedia.o ...
- Node.js,commonjs,require
环境: Node应用由模块组成,采用CommonJS模块规范. node的全局对象是global,没有window这个对象. process表示当前执行的进程,挂在global之下. CommonJS ...
- acdrem1083 人民城管爱人民 DP
思路:d(i, 0)表示从节点i到达大运村的最短路径,d(i, 1)表示从节点i到达大运村的次短路径. 1.最短路:当做DAG处理即可. 2.次短路:假设当前在u点处,下一个节点是v.v到终点的最短路 ...
- 使用lambda编程之延迟执行
使用lambda表达式的主要原因是,将代码的执行延迟到一个合适的时间点. 所有的lambda表达式都是延迟执行的.毕竟,如果你希望立即执行一段代码,那就没有必要使用lambda表达式了.延迟执行代码的 ...
- pycharm安装,svn使用,远程开发调试,接口测试,连接服务器
磨刀不误砍柴工,配置完美的编辑器,在开发时,能帮助我们节约大量的时间成本,从而是我们的精力放在业务逻辑实现上面! 接下来将介绍 使用pyhcarm如何使用svn,远程开发调试,接口测试,已经连接远程服 ...
- B树、B-树、B+树、B*树【转】,mysql索引
B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...
- linux及hadoop修改权限
linux下修改文件权限: 在shell环境里输入:ls -l 或者 ls -lh drwxr-xr-x 2 nsf users 1024 12-10 17:37 下载文件备份对应:文件属性 连接数 ...