Redis 是我們?cè)陂_發(fā)過程中經(jīng)常會(huì)用到的內(nèi)存數(shù)據(jù)庫(kù),尤其是在Python的第三方模塊Redis-py的支持下,在Python中使用Redis及其方便。
但是在有些情況下,我們無法使用像Redis-py這樣的第三方模塊(比如QMT),這時(shí)候就需要自己實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的Redis-py了。
本文將教大家如何用20行代碼,制作一個(gè)簡(jiǎn)易版的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'
可見其是一個(gè)bytes字符串,開頭$xxx是此數(shù)據(jù)的長(zhǎng)度,rn作為分割符,后面緊跟著的就是你的原始數(shù)據(jù)內(nèi)容,最后才是rn作為結(jié)尾。
根據(jù)這個(gè)返回內(nèi)容,我們就可以制作一個(gè)簡(jiǎn)易的客戶端用于在無法引用第三方模塊的環(huán)境中接收Redis信息。
3.編寫簡(jiǎn)易R(shí)edis客戶端
與Redis通信,我們只需要用Python原生的socket模塊即可。
import socket
import pickle
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 創(chuàng)建 socket 對(duì)象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
s.close()
這樣就與你的Redis服務(wù)器連接上了,接下來只需要向socket發(fā)送你的命令并receive即可獲取對(duì)應(yīng)的內(nèi)容:
import socket
import pickle
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
# 創(chuàng)建 socket 對(duì)象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某個(gè) 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'
請(qǐng)注意,recv里你設(shè)定的大小會(huì)直接占用內(nèi)存,所以請(qǐng)?jiān)O(shè)定一個(gè)適宜的數(shù)目,或者從返回值中的美元符后的數(shù)字判斷你需要接收的數(shù)據(jù)大小。
比如第一次請(qǐng)求,你只接收1024個(gè)字節(jié),拿到 $xxx 這個(gè)長(zhǎng)度后,重新send一次命令,再 s.recv(xxx) 長(zhǎng)度。
上述例子中得到的內(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 對(duì)象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接服務(wù),指定主機(jī)和端口
s.connect((REDIS_HOST, REDIS_PORT))
# GET 某個(gè) 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等會(huì)限制第三方模塊的軟件中,使用這樣的方式訪問Redis,就不會(huì)再遇到白名單的限制了。
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
2903瀏覽量
73536 -
開發(fā)
+關(guān)注
關(guān)注
0文章
357瀏覽量
40734 -
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3712瀏覽量
64023 -
Redis
+關(guān)注
關(guān)注
0文章
368瀏覽量
10780
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論