Redis 是我們在開發(fā)過程中經(jīng)常會用到的內(nèi)存數(shù)據(jù)庫,尤其是在Python的第三方模塊Redis-py的支持下,在Python中使用Redis及其方便。
但是在有些情況下,我們無法使用像Redis-py這樣的第三方模塊(比如QMT),這時候就需要自己實(shí)現(xiàn)一個簡易版的Redis-py了。
本文將教大家如何用20行代碼,制作一個簡易版的Redis客戶端,不過僅以GET命令為例,其他命令的用法也差不多。
1.準(zhǔn)備
開始之前,你要確保Python和pip已經(jīng)成功安裝在電腦上,如果沒有,可以訪問這篇文章:超詳細(xì)Python安裝指南 進(jìn)行安裝。
**(可選1) **如果你用Python的目的是數(shù)據(jù)分析,可以直接安裝Anaconda:Python數(shù)據(jù)分析與挖掘好幫手—Anaconda,它內(nèi)置了Python和pip.
**(可選2) **此外,推薦大家用VSCode編輯器,它有許多的優(yōu)點(diǎn):Python 編程的最好搭檔—VSCode 詳細(xì)指南。
2.原理剖析
其實(shí)通過Redis GET返回的數(shù)據(jù)就是一些字符串,這些字符串的格式如下:
b'$466rnx80x04x95xc7x01x00x00x00x00x00x00]x94(x8cx06000957x94x8cx06002031x94x8cx06000899x94x8cx06300339x94x8cx06002090x94x8cx06601016x94x8cx06002547x94x8cx06002863x94x8cx06002591x94x8cx06002514x94x8cx06000629x94x8cx06002204x94x8cx06000544x94x8cx06002374x94x8cx06000821x94x8cx06000625x94x8cx06000158x94x8cx06002703x94x8cx06002866x94x8cx06600686x94x8cx06002796x94x8cx06300598x94x8cx06002101x94x8cx06002454x94x8cx06000970x94x8cx06000631x94x8cx06002121x94x8cx06600348x94x8cx06600996x94x8cx06002080x94x8cx06002194x94x8cx06002466x94x8cx06300663x94x8cx06002616x94x8cx06000665x94x8cx06600992x94x8cx06300750x94x8cx06300059x94x8cx06002047x94x8cx06002997x94x8cx06000521x94x8cx06002594x94x8cx06002261x94x8cx06002125x94x8cx06002085x94x8cx06002168x94x8cx06002665x94x8cx06002523x94x8cx06603067x94x8cx06002432x94e.rn'
可見其是一個bytes字符串,開頭$xxx是此數(shù)據(jù)的長度,rn作為分割符,后面緊跟著的就是你的原始數(shù)據(jù)內(nèi)容,最后才是rn作為結(jié)尾。
根據(jù)這個返回內(nèi)容,我們就可以制作一個簡易的客戶端用于在無法引用第三方模塊的環(huán)境中接收Redis信息。
3.編寫簡易Redis客戶端
與Redis通信,我們只需要用Python原生的socket模塊即可。
import socket
import pickle
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 創(chuàng)建 socket 對象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
s.close()
這樣就與你的Redis服務(wù)器連接上了,接下來只需要向socket發(fā)送你的命令并receive即可獲取對應(yīng)的內(nèi)容:
import socket
import pickle
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 創(chuàng)建 socket 對象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某個 KEY 的內(nèi)容
s.send("GET RQB_keys_20220719 rn".encode("utf-8"))
# 接收小于 1M 的數(shù)據(jù)
msg = s.recv(1024 * 1024)
s.close()
print(msg)
# b'$466rnx80x04x95xc7x01x00x00x00x00x00x00]x94(x8cx06000957x94x8cx06002031x94x8cx06000899x94x8cx06300339x94x8cx06002090x94x8cx06601016x94x8cx06002547x94x8cx06002863x94x8cx06002591x94x8cx06002514x94x8cx06000629x94x8cx06002204x94x8cx06000544x94x8cx06002374x94x8cx06000821x94x8cx06000625x94x8cx06000158x94x8cx06002703x94x8cx06002866x94x8cx06600686x94x8cx06002796x94x8cx06300598x94x8cx06002101x94x8cx06002454x94x8cx06000970x94x8cx06000631x94x8cx06002121x94x8cx06600348x94x8cx06600996x94x8cx06002080x94x8cx06002194x94x8cx06002466x94x8cx06300663x94x8cx06002616x94x8cx06000665x94x8cx06600992x94x8cx06300750x94x8cx06300059x94x8cx06002047x94x8cx06002997x94x8cx06000521x94x8cx06002594x94x8cx06002261x94x8cx06002125x94x8cx06002085x94x8cx06002168x94x8cx06002665x94x8cx06002523x94x8cx06603067x94x8cx06002432x94e.rn'
請注意,recv里你設(shè)定的大小會直接占用內(nèi)存,所以請?jiān)O(shè)定一個適宜的數(shù)目,或者從返回值中的美元符后的數(shù)字判斷你需要接收的數(shù)據(jù)大小。
比如第一次請求,你只接收1024個字節(jié),拿到 $xxx 這個長度后,重新send一次命令,再 s.recv(xxx) 長度。
上述例子中得到的內(nèi)容是redis的格式,我們需要把rn給去除掉,并只取中間的數(shù)據(jù)便是我們存入redis的原始數(shù)據(jù)。
import pickle
def get_msg(msg):
msg_new = msg.split(b"rn")[1]
msg = pickle.loads(msg_new)
return msg
因?yàn)槲业脑純?nèi)容是pickle格式,因此我在取出原始數(shù)據(jù)后使用pickle.loads便能拿到我想要的內(nèi)容,完整代碼如下:
import socket
import pickle
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 創(chuàng)建 socket 對象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某個 KEY 的內(nèi)容
s.send("GET RQB_keys_20220719 rn".encode("utf-8"))
# 接收小于 1M 的數(shù)據(jù)
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,就不會再遇到白名單的限制了。
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
3125瀏覽量
75274 -
開發(fā)
+關(guān)注
關(guān)注
0文章
373瀏覽量
41523 -
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3927瀏覽量
66261 -
Redis
+關(guān)注
關(guān)注
0文章
387瀏覽量
11452
發(fā)布評論請先 登錄
信號處理原理-簡易版
一個服務(wù)器,多個客戶端,怎么向指定的客戶端發(fā)數(shù)據(jù)
阿里云專訪Redisson作者Rui Gu:構(gòu)建開源企業(yè)級Redis客戶端之路
用Delphi開發(fā)OPC客戶端工具的方法研究
CoolpyCould客戶端
Redis的數(shù)據(jù)結(jié)構(gòu)和主要命令對Redis的基本能力進(jìn)行直觀介紹
iOS端淘寶客戶端應(yīng)用名稱發(fā)生變化 Android客戶端應(yīng)用名稱尚未更改
MQTT中服務(wù)端和客戶端
ROS是如何設(shè)計(jì)的 ROS客戶端庫

評論