中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

自己動手寫一個能操作redis的客戶端

作者:孤獨(dú)煙 來源:微信訂閱號(程序員孤獨(dú)煙)

原文鏈接: https://mp.weixin.qq.com/s/IBynkex-FHhvJ3tmizvJhA

成都創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、三門網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5網(wǎng)站設(shè)計、成都做商城網(wǎng)站、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為三門等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

引言

redis大家在項目中經(jīng)常會使用到。官網(wǎng)也提供了多語言的客戶端供大家操作redis,如下圖所示

自己動手寫一個能操作redis的客戶端

但是,大家有思考過,這些語言操作redis背后的原理么?其實,某些大神會說

只要按照redis的協(xié)議,發(fā)送指定數(shù)據(jù)給redis,監(jiān)聽返回值即可。


確實,本質(zhì)原理就是如上面那句話所說。博主也是以這種思路,去看了一下JAVA端的開源組件jedis的源碼,然后取其精華,寫了一個段能操作redis的demo,希望大家能有所收獲。


jedis的github地址為:
https://github.com/xetorthio/jedis


有興趣的童鞋,也可以自行去閱讀。需要說明的是,這畢竟不是源碼分析系列文章,不是帶你去看jedis的源碼。只是借鑒思路,寫一個能操作redis的程序。

正文

首先,我先說一下操作思路,如下圖所示

自己動手寫一個能操作redis的客戶端

說明一下,上面的第四步,就是我們自己要寫的操作redis的小demo。

1、先寫一個socket監(jiān)聽6379端口

這個程序很easy,度娘一下出來一大把

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(6379);
        Socket socket = server.accept();
        byte[] chars = new byte[64];
        socket.getInputStream().read(chars);
        System.out.println(new String(chars));
    }
}

2、采用開源客戶端,操作一次redis

我這里用的是JAVA語言的jedis,大家自己也可以用其他的任意語言組件,目的是為了采集客戶端在操作redis時,發(fā)送出的數(shù)據(jù)

import redis.clients.jedis.Jedis;
public class RedisTest {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.set("eat", "I want to eat");
    }
}

3、看看socket監(jiān)聽到的數(shù)據(jù)

在這里運(yùn)行一下第二步的代碼,查看第一步的代碼輸出的數(shù)據(jù),如下所示

*3
$3
SET
$3
eat
$13
I want to eat

那么,這組數(shù)據(jù)是什么含義呢?
我們?nèi)ス倬W(wǎng)進(jìn)行查詢。原來,redis的客戶端和服務(wù)端采取了一種RESP協(xié)議。相應(yīng)文檔地址如下
https://redis.io/topics/protocol
RESP設(shè)計巧妙,它的前景在于下面三個方面:

  • Simple to implement.

  • Fast to parse.

  • Human readable.

那么+、-、*、:、$這些符號是什么意思呢?
官網(wǎng)有這么一段話

In RESP, the type of some data depends on the first byte:  For Simple Strings the first byte of the reply is "+"
 For Errors the first byte of the reply is "-"
 For Integers the first byte of the reply is ":"
 For Bulk Strings the first byte of the reply is "$"
 For Arrays the first byte of the reply is "*"
 Additionally RESP is able to represent a Null value using a special variation of Bulk Strings or Array as specified later.
 In RESP different parts of the protocol are always terminated with "\r\n" (CRLF).

翻譯過來
(1)簡單字符串Simple Strings, 以 "+"加號 開頭
(2)錯誤Errors, 以"-"減號 開頭
(3)整數(shù)型Integer, 以 ":" 冒號開頭
(4)大字符串類型Bulk Strings, 以 "$"美元符號開頭,長度限制512M
(5)組類型Arrays,以 "*"星號開頭
并且,協(xié)議的每部分都是以 "\r\n" (CRLF) 結(jié)尾的。

OK,那我們剛才的那一串的數(shù)據(jù)的意思就是(沒有看到""\r\n",是因為已經(jīng)轉(zhuǎn)義了,所以無法看到):

*3   數(shù)組包含3個元素,分別是SET、eat、I want to eat
$3   是一個字符串,且字符串長度為3
SET  字符串的內(nèi)容
$3   是一個字符串,且字符串長度為3
eat  字符串的內(nèi)容
$13  是一個字符串,且字符串長度為13
I want to eat 字符串的內(nèi)容

提問,如果是get命令,那么傳輸?shù)腞ESP的內(nèi)容長什么樣?
比如有一個命令get eat,那么此時的內(nèi)容如下所示

*2
$3
GET
$3
eat

沒有\(zhòng)r\n是因為已經(jīng)轉(zhuǎn)義了,所以沒看到。其他的命令,可以自行測試。

4、嘗試構(gòu)造一樣的數(shù)據(jù)操作redis

OK,經(jīng)過上面的鋪墊。我們?nèi)绻獙edis做一個set操作,則構(gòu)造set命令的RESP協(xié)議內(nèi)容,并且利用socket編程,將這串內(nèi)容發(fā)送給redis即可。這里用java的socket編程實現(xiàn),用其他語言也是一樣的。
我們有一個類 RedisClient.java
代碼如下

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class RedisClient {
    private Socket socket;                                     
    private OutputStream outputStream;
    private InputStream inputStream;
    public RedisClient(String host, int port){
        try {
            this.socket = new Socket(host,port);
            this.outputStream = this.socket.getOutputStream();
            this.inputStream = this.socket.getInputStream();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public String set(final String key, String value) {
        StringBuilder sb = new StringBuilder();
        //雖然輸出的時候,會被轉(zhuǎn)義,然而我們傳送的時候還是要帶上\r\n
        sb.append("*3").append("\r\n");
        sb.append("$3").append("\r\n");
        sb.append("SET").append("\r\n");
        sb.append("$").append(key.length()).append("\r\n");
        sb.append(key).append("\r\n");
        sb.append("$").append(value.length()).append("\r\n");
        sb.append(value).append("\r\n");
        byte[] bytes= new byte[1024];
        try {
            outputStream.write(sb.toString().getBytes());
            inputStream.read(bytes);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return new String(bytes);
    }
    public static void main(String[] args) {
        RedisClient redisClient = new RedisClient("127.0.0.1", 6379);
        String result = redisClient.set("eat", "please eat");
        System.out.println(result);     
    }
}

上面的public String set(final String key, String value)方法中,顯示了,我們假如需要對redis進(jìn)行set操作,需要傳輸?shù)腞ESP協(xié)議的內(nèi)容。記住,一定要帶\r\n字符作為結(jié)尾
OK,運(yùn)行上述代碼,你會發(fā)現(xiàn)你可以往redis中set數(shù)據(jù)了,并且控制臺輸出如下

+OK

提問,你自己會封裝get命令么?

總結(jié)

本文以一種循序漸進(jìn)的方式帶領(lǐng)大家寫了一個能操作redis的demo,希望大家有所收獲。

當(dāng)前文章:自己動手寫一個能操作redis的客戶端
文章位置:http://www.rwnh.cn/article2/gcgpic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、Google、網(wǎng)站建設(shè)自適應(yīng)網(wǎng)站、定制開發(fā)、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)
旌德县| 闸北区| 永和县| 泰宁县| 武功县| 莱西市| 永泰县| 和田县| 阿拉善右旗| 东港市| 宜兰县| 甘谷县| 大港区| 义乌市| 旬阳县| 宝坻区| 苍梧县| 周口市| 扎兰屯市| 黑龙江省| 蓝山县| 六枝特区| 西乡县| 乐山市| 宁晋县| 砀山县| 奉化市| 临江市| 四会市| 铅山县| 大理市| 金湖县| 友谊县| 纳雍县| 进贤县| 光山县| 彭阳县| 吉安市| 连山| 平邑县| 榆林市|