go實(shí)現(xiàn)Redis讀寫分離示例詳解
我們?yōu)槭裁葱枰私釸ESP協(xié)議?
本篇文章目的為探究RESP協(xié)議,而非編寫讀寫中間件,這點(diǎn)要清楚。
關(guān)于這個(gè)問(wèn)題,我想通過(guò)一個(gè)實(shí)例來(lái)解釋,我們編寫Redis中間件,為什么需要了解RESP協(xié)議。

以上代碼是編寫了一個(gè)非常簡(jiǎn)單的TCP服務(wù)器,我們監(jiān)聽(tīng)8888端口,嘗試使用redis-cli -p 8888連接服務(wù)器后,而后查看打印出來(lái)的應(yīng)用層報(bào)文。
我們嘗試執(zhí)行下該代碼,并且輸入redis-cli -p 8888進(jìn)行連接。

我們編寫的服務(wù)器獲取redis客戶端的報(bào)文為:
*1
$7
COMMAND
上面這個(gè)就是RESP協(xié)議的內(nèi)容了,所以說(shuō),我們要編寫一個(gè)Redis的中間件,我們需要先了解一下RESP協(xié)議才行。
什么是RESP協(xié)議
官網(wǎng)有相關(guān)的解釋: https://redis.io/docs/reference/protocol-spec/
RESP協(xié)議創(chuàng)建之初是專門為了Redis服務(wù)器和客戶端的通信而設(shè)計(jì)的,該協(xié)議在Redis 1.2中引入,并且在Redis 2.0中,成為Redis通信的標(biāo)準(zhǔn)協(xié)議。該協(xié)議有如下優(yōu)點(diǎn):
- 實(shí)現(xiàn)簡(jiǎn)單
- 快速解析
- 直接可閱讀
RESP根據(jù)其協(xié)議前綴,可以序列化不同的數(shù)據(jù)類型,例如: 整數(shù)、字符串、數(shù)組 等,還能標(biāo)注 正常輸出 和 錯(cuò)誤輸出等。除了流水線和發(fā)布訂閱以外,RESP協(xié)議應(yīng)該是最簡(jiǎn)單的請(qǐng)求-響應(yīng)協(xié)議了。關(guān)于更多介紹,大佬們可以看看上面注釋的官方文檔。
RESP協(xié)議規(guī)范
RESP協(xié)議不同的部分使用\r\n(換行符)來(lái)進(jìn)行分割,其支持5種數(shù)據(jù)類型,分別為: 簡(jiǎn)單字符串、錯(cuò)誤、整數(shù)、復(fù)雜字符串 和 數(shù)組組成,我們列個(gè)表格來(lái)講下。
| 類型 | 前綴 | 備注 |
|---|---|---|
| 簡(jiǎn)單字符串 | + | 簡(jiǎn)單字符串以+開(kāi)頭 |
| 錯(cuò)誤數(shù)據(jù) | - | 錯(cuò)誤數(shù)據(jù)以-開(kāi)頭 |
| 整數(shù) | : | 整數(shù)以:開(kāi)頭 |
| 復(fù)雜字符串 | $ | 復(fù)雜字符串以$開(kāi)頭 |
| 數(shù)組 | * | 數(shù)組以*開(kāi)頭 |
我當(dāng)初看到這個(gè)的時(shí)候,也是迷迷糊糊的,到底什么意思呢? 哎,我們舉個(gè)例子你就明白了。
若我們想執(zhí)行
set juejinName pdudo
若使用RESP 協(xié)議應(yīng)當(dāng)如何編寫呢?應(yīng)當(dāng)編寫如下:
*3 $3 set $10 juejinName $5 pdudo
那我們來(lái)解釋一下*3代表有3個(gè)數(shù)組,而$3代表復(fù)雜字符串有長(zhǎng)度為3,值為set, $10代表復(fù)雜字符串長(zhǎng)度為10,值為juejinName, $5代表復(fù)雜字符串長(zhǎng)度為5,值為pdudo。
我們結(jié)合上述信息,可以畫一張圖。

這就是協(xié)議的內(nèi)容了。
而協(xié)議前綴+、-、:則要簡(jiǎn)單的多,直接跟數(shù)據(jù)即可,
例如:
+
+OK
-
-ERR syntax error
:
:3
如何使用該協(xié)議請(qǐng)求Redis
我們已經(jīng)學(xué)習(xí)了相關(guān)的RESP協(xié)議,那么我們?nèi)绾螌W(xué)習(xí)呢? 我們可以使用telnet命令來(lái)操作即可。
在此,我們準(zhǔn)備幾條命令,我們會(huì)將其轉(zhuǎn)換為RESP格式,且將其發(fā)送到redis服務(wù)器。
命令
set name pdudo get name lpush pn 1 llen pn
轉(zhuǎn)換為RESP格式
*3 $3 set $4 name $5 pdudo *2 $3 get $4 name *3 $5 lpush $2 pn $1 1 *2 $4 llen $2 pn
我們將其放置到telnet中執(zhí)行一下呢

現(xiàn)在回頭看看官網(wǎng)文檔所提及的,該協(xié)議實(shí)現(xiàn)簡(jiǎn)單,直接可閱讀,是不是理解的更加深刻了呢?
使用go編寫Redis中間件實(shí)現(xiàn)讀寫分離
本篇暫不解釋代碼,而后單獨(dú)開(kāi)一篇談?wù)撝虚g件代碼。
實(shí)現(xiàn)該功能,其實(shí)本質(zhì)上是區(qū)分命令是查詢還是寫入,若是查詢,則直接轉(zhuǎn)發(fā)到從庫(kù),而寫入,則轉(zhuǎn)發(fā)到主庫(kù)即可,其架構(gòu)圖可以理解為如下:

我們已經(jīng)有了目前的架構(gòu)。
| 主機(jī) | 端口 | 密碼 | 角色 |
|---|---|---|---|
| 127.0.0.1 | 6379 | 無(wú) | 主庫(kù) |
| 127.0.0.1 | 7380 | 無(wú) | 從庫(kù) |
相關(guān)代碼已經(jīng)放到了 gitee.com/pdudo/golea…
我們來(lái)看看實(shí)際效果呢:

總結(jié)
其實(shí)本篇文章核心的點(diǎn)是探究RESP協(xié)議,而我們使用go編寫了一個(gè)軟件,用于解析RESP協(xié)議,從而獲取執(zhí)行的命令,再根據(jù)命令屬性,從而轉(zhuǎn)發(fā)從庫(kù)或者主庫(kù),以此來(lái)達(dá)到讀寫分離的效果。再次提及一下核心點(diǎn)是拆解RESP協(xié)議。
怎么樣,好玩吧,動(dòng)動(dòng)你的小手指,快來(lái)試試吧。
以上就是go實(shí)現(xiàn)Redis讀寫分離示例詳解的詳細(xì)內(nèi)容,更多關(guān)于go Redis讀寫分離的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang命令行進(jìn)行debug調(diào)試操作
今天小編就為大家分享一篇關(guān)于,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04
利用Go語(yǔ)言開(kāi)發(fā)文件操作工具輕松處理所有文件
在后端開(kāi)發(fā)中,文件操作是一個(gè)非常常見(jiàn)但又容易出錯(cuò)的場(chǎng)景,本文小編要向大家介紹一個(gè)強(qiáng)大的 Go 語(yǔ)言文件操作工具庫(kù),它能幫你輕松處理各種文件操作場(chǎng)景2025-03-03
golang如何使用struct的tag屬性的詳細(xì)介紹
這篇文章主要介紹了golang如何使用struct的tag屬性的詳細(xì)介紹,從例子說(shuō)起,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Golang實(shí)現(xiàn)JWT身份驗(yàn)證的示例詳解
JWT(JSON Web Token)是一種開(kāi)放標(biāo)準(zhǔn)(RFC 7519),用于在網(wǎng)絡(luò)應(yīng)用間安全地傳輸聲明,本文主要為大家詳細(xì)介紹了Golang實(shí)現(xiàn)JWT身份驗(yàn)證的相關(guān)方法,希望對(duì)大家有所幫助2024-03-03
利用golang和shell計(jì)算一個(gè)字符串的md5值
這篇文章主要介紹了如何利用golang和shell計(jì)算一個(gè)字符串的md5值,我們先用shell來(lái)計(jì)算一下,再去判斷golang計(jì)算的md5值是否正確,文中有詳細(xì)的圖文介紹,需要的朋友可以參考下2024-03-03

