国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用Go實(shí)現(xiàn)Redis之三get/set命令實(shí)現(xiàn)

Ethan815 / 2899人閱讀

摘要:在讀者閱讀實(shí)現(xiàn)代碼時(shí),也可以看到最新版本,與有一處是在文件清除掉回車換行符該行被暫時(shí)注釋掉,也就是在版本,使用作為文本協(xié)議分隔符,確定命令的結(jié)尾。

寫在前面

本篇Godis版本號(hào):v0.0.2

前一篇文章實(shí)現(xiàn)了客戶端/服務(wù)端的交互。這一篇,主要介紹get/set命令的實(shí)現(xiàn)。
命令本身比較簡(jiǎn)單,支撐命令的整個(gè)系統(tǒng)基礎(chǔ)比較麻煩。本文會(huì)介紹get/set操作涉及的組件和模塊,并適當(dāng)簡(jiǎn)化,最后實(shí)現(xiàn)功能。

Redis用C語(yǔ)言寫成,C語(yǔ)言自身不支持復(fù)雜數(shù)據(jù)結(jié)構(gòu),所以Redis中的string、list、set等結(jié)構(gòu),均是Redis自身實(shí)現(xiàn);而Go版本的Godis,會(huì)盡量使用原生數(shù)據(jù)結(jié)構(gòu)。


原理簡(jiǎn)介

set命令和get命令是Redis中使用頻率最高的命令,以set為例,命令“set key value”,將鍵值對(duì)存儲(chǔ)到Redis服務(wù)端,可以簡(jiǎn)化為“操作一個(gè)遠(yuǎn)程關(guān)聯(lián)數(shù)組”。
當(dāng)然,相比關(guān)聯(lián)數(shù)組,Redis多了如下特性:

多DB,支持?jǐn)?shù)據(jù)庫(kù)切換;

高可用之?dāng)?shù)據(jù)持久化;

高可用之主從復(fù)制;

安全、事務(wù)、發(fā)布訂閱等。

本文重點(diǎn)實(shí)現(xiàn)數(shù)據(jù)在內(nèi)存中的存儲(chǔ)及查詢,交互協(xié)議和持久化會(huì)在后續(xù)短文實(shí)現(xiàn)。

執(zhí)行流程 流程拆解

從服務(wù)端初始化、客戶端輸入“set alpha 123”命令,到接收到返回結(jié)果,經(jīng)歷如下步驟:

實(shí)例化server及相關(guān)資源,準(zhǔn)備連接;

客戶端與服務(wù)端建立連接,服務(wù)端初始化一個(gè)client結(jié)構(gòu)體,用來(lái)保存當(dāng)前連接;

將客戶端請(qǐng)求的“set alpha 123”字符串,分拆為“set”、“alpha”、“123”三部分;

查找是否支持set命令,并確定參數(shù)合法,調(diào)set用命令的實(shí)現(xiàn)函數(shù)SetCommand,更新db數(shù)據(jù);

執(zhí)行結(jié)果響應(yīng)給客戶端;

執(zhí)行流程大致如下:


接下來(lái)分開說明主要步驟。

1.數(shù)據(jù)交互

前篇實(shí)現(xiàn)的客戶端/服務(wù)端交互使用的協(xié)議是textproto,沒有使用Redis自身的統(tǒng)一協(xié)議。這一篇,客戶端對(duì)服務(wù)端執(zhí)行的get、set命令,均以原生文本方式發(fā)送給服務(wù)端執(zhí)行。在讀者閱讀實(shí)現(xiàn)代碼時(shí),也可以看到最新release版本,與v0.0.1有一處diff是在godis-cli.go文件:

//清除掉回車換行符
//text = strings.Replace(text, "
", "", -1)

該行被暫時(shí)注釋掉,也就是在v0.0.2版本,使用“n”作為文本協(xié)議分隔符,確定命令的結(jié)尾。

如客戶端發(fā)送"set alpha 123",服務(wù)端接收到的就是如下字節(jié)數(shù)據(jù):

分別對(duì)應(yīng)ASCII碼為:

2.服務(wù)端準(zhǔn)備

第一篇(https://segmentfault.com/a/11...)提到過服務(wù)端需要一個(gè)server結(jié)構(gòu)體存儲(chǔ)相關(guān)信息,在服務(wù)端準(zhǔn)備好處理請(qǐng)求前,對(duì)該結(jié)構(gòu)進(jìn)行實(shí)例化并進(jìn)行一系列初始化操作:初始化基本配置、分配多db資源、加載磁盤持久化數(shù)據(jù)、信號(hào)監(jiān)聽處理等。
初始化server的代碼主要是一些賦值操作和相應(yīng)結(jié)構(gòu)體初始化:

// 初始化服務(wù)端實(shí)例
func initServer() {
    godis.Pid = os.Getpid()
    godis.DbNum = 16
    initDb()
    godis.Start = time.Now().UnixNano() / 1000000
    //var getf server.CmdFun

    getCommand := &core.GodisCommand{Name: "get", Proc: core.GetCommand}
    setCommand := &core.GodisCommand{Name: "set", Proc: core.SetCommand}

    godis.Commands = map[string]*core.GodisCommand{
        "get": getCommand,
        "set": setCommand,
    }
}

// 初始化db
func initDb() {
    godis.Db = make([]*core.GodisDb, godis.DbNum)
    for i := 0; i < godis.DbNum; i++ {
        godis.Db[i] = new(core.GodisDb)
        godis.Db[i].Dict = make(map[string]*core.GodisObject, 100)
    }
}

這里簡(jiǎn)單解釋下core.GodisCommand結(jié)構(gòu)。該結(jié)構(gòu)很簡(jiǎn)單,記錄了命令的名字、函數(shù)指針和參數(shù)校驗(yàn)相關(guān)的信息。在執(zhí)行命令前,校驗(yàn)命令是否存在的過程,需要查找支持的”命令表“。該命令表就是commands,commands由一組core.GodisCommand構(gòu)成。commands中查不到的命令,則為不支持的命令;而命令參數(shù)需要滿足哪些條件,由core.GodisCommand結(jié)構(gòu)的其他字段記錄。

3.服務(wù)端接收

當(dāng)服務(wù)端準(zhǔn)備就緒,開始接受請(qǐng)求。
請(qǐng)求到來(lái),server會(huì)實(shí)例化一個(gè)client結(jié)構(gòu)體,保存當(dāng)前連接。該client結(jié)構(gòu)體也在前篇有介紹,主要用來(lái)存儲(chǔ)當(dāng)前連接的db等信息。

// CreateClient 連接建立 創(chuàng)建client記錄當(dāng)前連接
func (s *Server) CreateClient(conn net.Conn) (c *Client) {
    c = new(Client)
    c.Db = s.Db[0]
    c.Argv = make([]*GodisObject, 5)
    c.QueryBuf = ""
    return c
}
4.執(zhí)行命令

將請(qǐng)求的命令分解,校驗(yàn)無(wú)誤后,調(diào)用響應(yīng)函數(shù)執(zhí)行。注意,只在當(dāng)前client結(jié)構(gòu)指向的db中執(zhí)行插入、查詢、更新等操作。如果需要操作其他db,執(zhí)行"select"命令便將當(dāng)前client指向的db指針指向select后的位置。
執(zhí)行完成后,將結(jié)果寫入到client結(jié)構(gòu)的Buf字段。

下面的handle函數(shù)包括了client的創(chuàng)建、數(shù)據(jù)接收、執(zhí)行和返回。

// 處理請(qǐng)求
func handle(conn net.Conn) {
    c := godis.CreateClient(conn)
    for {
        err := c.ReadQueryFromClient(conn)

        if err != nil {
            log.Println("readQueryFromClient err", err)
            return
        }
        c.ProcessInputBuffer()
        godis.ProcessCommand(c)
        responseConn(conn, c)
    }
}
// ProcessCommand 執(zhí)行命令
func (s *Server) ProcessCommand(c *Client) {
    v := c.Argv[0].Ptr
    name, ok := v.(string)
    if !ok {
        log.Println("error cmd")
        os.Exit(1)
    }
    cmd := lookupCommand(name, s)
    if cmd != nil {
        c.Cmd = cmd
        call(c, s)
    } else {
        addReply(c, CreateObject(ObjectTypeString, fmt.Sprintf("(error) ERR unknown command "%s"", name)))
    }
}

ProcessCommand函數(shù)先從命令表中查找命令,如果存在,調(diào)用該命令的實(shí)現(xiàn),并將結(jié)果寫入client.Buf字段。

5.響應(yīng)請(qǐng)求

將client.Buf內(nèi)容,返回給請(qǐng)求方,完成。
最后將執(zhí)行結(jié)果返回給請(qǐng)求方。

// 響應(yīng)返回給客戶端
func responseConn(conn net.Conn, c *core.Client) {
    conn.Write([]byte(c.Buf))
}
測(cè)試

分別編譯服務(wù)端和命令行客戶端:
go build godis-server.go
go build godis-server.go

啟動(dòng) ./godis-server

1.非法命令:

?

2.set/get命令:

服務(wù)端啟動(dòng):

cli請(qǐng)求:

本篇問題

文本協(xié)議的格式分隔符沒有處理好,在服務(wù)端又是使用的conn.Read(buff),讀入的數(shù)據(jù)與buff額外的緩沖區(qū)混在一起。而print字符串又屏蔽了有效字符串后全零的問題(print調(diào)試最好輸出原始數(shù)據(jù))。

下集預(yù)告

1. 實(shí)現(xiàn)Redis統(tǒng)一協(xié)議

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/28809.html

相關(guān)文章

  • Go實(shí)現(xiàn)Redis之四實(shí)現(xiàn)Redis的協(xié)議交互

    摘要:在本文,將替換文本協(xié)議為版本后的統(tǒng)一協(xié)議。協(xié)議格式在發(fā)送命令和返回結(jié)果中均使用同一套標(biāo)準(zhǔn)協(xié)議。實(shí)現(xiàn)通信協(xié)議版本協(xié)議實(shí)現(xiàn)初探很多相關(guān)的組件模塊工具都有協(xié)議的生成和解析實(shí)現(xiàn),并歷經(jīng)生產(chǎn)環(huán)境的考驗(yàn)。 寫在前面 本文實(shí)現(xiàn)的Godis代碼版本為:v0.0.3 在前三篇文章中,實(shí)現(xiàn)了客戶端/服務(wù)端的交互(基于textprotoco)、服務(wù)端初始化和get/set命令。如果閱讀過或者調(diào)試過粗略的代碼...

    legendmohe 評(píng)論0 收藏0
  • Go實(shí)現(xiàn)Redis之二客戶端/服務(wù)端交互

    摘要:寫在前面在前一篇梳理了版本的基本功能,這一篇要做的是實(shí)現(xiàn)客戶端服務(wù)端的交互。進(jìn)入正題事件處理器既要實(shí)現(xiàn)交互,網(wǎng)絡(luò)編程必不可少。 寫在前面 在前一篇梳理了Godis v1.0版本的基本功能,這一篇要做的是實(shí)現(xiàn)客戶端/服務(wù)端的交互。先讓代碼跑起來(lái),才算有了生命力。本篇Godis版本號(hào):v0.0.1 在這個(gè)系列文章里,盡量減少介紹Golang語(yǔ)法、C語(yǔ)言語(yǔ)法和redis原理,聚焦在用Gol...

    Scliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<