如何制作简易版的Redis客户端

描述

Redis 是我们在开发过程中经常会用到的内存数据库,尤其是在Python的第三方模块Redis-py的支持下,在Python中使用Redis及其方便。

但是在有些情况下,我们无法使用像Redis-py这样的第三方模块(比如QMT),这时候就需要自己实现一个简易版的Redis-py了。

本文将教大家如何用20行代码,制作一个简易版的Redis客户端,不过仅以GET命令为例,其他命令的用法也差不多。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,可以访问这篇文章:超详细Python安装指南 进行安装。

**(可选1) **如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

**(可选2) **此外,推荐大家用VSCode编辑器,它有许多的优点:Python 编程的最好搭档—VSCode 详细指南

2.原理剖析

其实通过Redis GET返回的数据就是一些字符串,这些字符串的格式如下:

b'$466rnx80x04x95xc7x01x00x00x00x00x00x00]x94(x8cx06000957x94x8cx06002031x94x8cx06000899x94x8cx06300339x94x8cx06002090x94x8cx06601016x94x8cx06002547x94x8cx06002863x94x8cx06002591x94x8cx06002514x94x8cx06000629x94x8cx06002204x94x8cx06000544x94x8cx06002374x94x8cx06000821x94x8cx06000625x94x8cx06000158x94x8cx06002703x94x8cx06002866x94x8cx06600686x94x8cx06002796x94x8cx06300598x94x8cx06002101x94x8cx06002454x94x8cx06000970x94x8cx06000631x94x8cx06002121x94x8cx06600348x94x8cx06600996x94x8cx06002080x94x8cx06002194x94x8cx06002466x94x8cx06300663x94x8cx06002616x94x8cx06000665x94x8cx06600992x94x8cx06300750x94x8cx06300059x94x8cx06002047x94x8cx06002997x94x8cx06000521x94x8cx06002594x94x8cx06002261x94x8cx06002125x94x8cx06002085x94x8cx06002168x94x8cx06002665x94x8cx06002523x94x8cx06603067x94x8cx06002432x94e.rn'

可见其是一个bytes字符串,开头$xxx是此数据的长度,rn作为分割符,后面紧跟着的就是你的原始数据内容,最后才是rn作为结尾。

根据这个返回内容,我们就可以制作一个简易的客户端用于在无法引用第三方模块的环境中接收Redis信息。

3.编写简易Redis客户端

与Redis通信,我们只需要用Python原生的socket模块即可。

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
s.close()

这样就与你的Redis服务器连接上了,接下来只需要向socket发送你的命令并receive即可获取对应的内容:

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某个 KEY 的内容
s.send("GET RQB_keys_20220719 rn".encode("utf-8"))
# 接收小于 1M 的数据
msg = s.recv(1024 * 1024)
s.close()
print(msg)
# b'$466rnx80x04x95xc7x01x00x00x00x00x00x00]x94(x8cx06000957x94x8cx06002031x94x8cx06000899x94x8cx06300339x94x8cx06002090x94x8cx06601016x94x8cx06002547x94x8cx06002863x94x8cx06002591x94x8cx06002514x94x8cx06000629x94x8cx06002204x94x8cx06000544x94x8cx06002374x94x8cx06000821x94x8cx06000625x94x8cx06000158x94x8cx06002703x94x8cx06002866x94x8cx06600686x94x8cx06002796x94x8cx06300598x94x8cx06002101x94x8cx06002454x94x8cx06000970x94x8cx06000631x94x8cx06002121x94x8cx06600348x94x8cx06600996x94x8cx06002080x94x8cx06002194x94x8cx06002466x94x8cx06300663x94x8cx06002616x94x8cx06000665x94x8cx06600992x94x8cx06300750x94x8cx06300059x94x8cx06002047x94x8cx06002997x94x8cx06000521x94x8cx06002594x94x8cx06002261x94x8cx06002125x94x8cx06002085x94x8cx06002168x94x8cx06002665x94x8cx06002523x94x8cx06603067x94x8cx06002432x94e.rn'

请注意,recv里你设定的大小会直接占用内存,所以请设定一个适宜的数目,或者从返回值中的美元符后的数字判断你需要接收的数据大小。

比如第一次请求,你只接收1024个字节,拿到 $xxx 这个长度后,重新send一次命令,再 s.recv(xxx) 长度。

上述例子中得到的内容是redis的格式,我们需要把rn给去除掉,并只取中间的数据便是我们存入redis的原始数据。

import pickle
def get_msg(msg):
    msg_new = msg.split(b"rn")[1]
    msg = pickle.loads(msg_new)
    return msg

因为我的原始内容是pickle格式,因此我在取出原始数据后使用pickle.loads便能拿到我想要的内容,完整代码如下:

import socket
import pickle

REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务,指定主机和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某个 KEY 的内容
s.send("GET RQB_keys_20220719 rn".encode("utf-8"))
# 接收小于 1M 的数据
msg = s.recv(1024 * 1024)
s.close()

def get_msg(msg):
    msg_new = msg.split(b"rn")[1]
    msg = pickle.loads(msg_new)
    return msg

print(get_msg(msg))

效果如下:

['000957', '002031', '000899', '300339', '002090', '601016', '002547', '002863', '002591', '002514', '000629', '002204', '000544', '002374', '000821', '000625', '000158', '002703', '002866', '600686', '002796', '300598', '002101', '002454', '000970', '000631', '002121', '600348', '600996', '002080', '002194', '002466', '300663', '002616', '000665', '600992', '300750', '300059', '002047', '002997', '000521', '002594', '002261', '002125', '002085', '002168', '002665', '002523', '603067', '002432']

在QMT等会限制第三方模块的软件中,使用这样的方式访问Redis,就不会再遇到白名单的限制了。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分