『互联网架构』软件架构-redis的通信协议(protocol)(52)

栏目: 数据库 · 发布时间: 6年前

内容简介:redis的通信协议是什么?双方约定了一种编码方式,客户端将要发送的命令进行编码,然后服务端收到后,使用同样的协议进行解码,服务端处理完成后,再次编码返回给客户端,客户端解码拿到返回结果,这样就完成了一次通信。

redis的通信协议是什么?双方约定了一种编码方式,客户端将要发送的命令进行编码,然后服务端收到后,使用同样的协议进行解码,服务端处理完成后,再次编码返回给客户端,客户端解码拿到返回结果,这样就完成了一次通信。

『互联网架构』软件架构-redis的通信协议(protocol)(52)

(一)协议介绍

 https://redis.io/topics/protocol 
  1. 易于实现
  2. 可以高效地被计算机分析(parse)
  3. 可以很容易地被人类读懂

『互联网架构』软件架构-redis的通信协议(protocol)(52)

(二)编码后的字符标记解释

  1. For Simple Strings the first byte of the reply is “+” 回复
  2. For Errors the first byte of the reply is “-” 错误
  3. For Integers the first byte of the reply is “:” 整数
  4. For Bulk Strings the first byte of the reply is “$” 字符串
  5. For Arrays the first byte of the reply is “*” 数组

(三)模拟 Redis 客户端&分片

  • 客户端

    > Jedis跟redis通讯很简单发送了socket,然后发送了resp这种‘暗语’进行通讯。

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class RedisClient {

    private Socket socket;
    private  String host;
    private int port;

    public RedisClient() throws IOException {
        this.socket = new Socket("192.168.79.100",6379);
    }

    public RedisClient(String host, int port) {
        this.host = host;
        this.port = port;
        try {
            this.socket = new Socket(host,port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //set wk 2018
    public String set( String key, String value) throws IOException {
       //"*3\r\n$3\r\nset\r\n$2\r\nwk\r\n$4\r\n2018"
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("*3").append("\r\n");
        stringBuilder.append("$").append(CommandRedis.set.name().length()).append("\r\n");
        stringBuilder.append(CommandRedis.set).append("\r\n");
        stringBuilder.append("$").append(key.getBytes().length).append("\r\n");
        stringBuilder.append(key).append("\r\n");
        stringBuilder.append("$").append(value.getBytes().length).append("\r\n");
        stringBuilder.append(value).append("\r\n");
        socket.getOutputStream().write(stringBuilder.toString().getBytes());
        byte[] b=new byte[2048];
        socket.getInputStream().read(b);
        return new String(b);

    }


    public String get( String key) throws IOException {
        //"*3\r\n$3\r\nset\r\n$2\r\nwk\r\n$4\r\n2018"
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("*2").append("\r\n");
        stringBuilder.append("$").append(CommandRedis.get.name().length()).append("\r\n");
        stringBuilder.append(CommandRedis.get).append("\r\n");
        stringBuilder.append("$").append(key.getBytes().length).append("\r\n");
        stringBuilder.append(key).append("\r\n");
        socket.getOutputStream().write(stringBuilder.toString().getBytes());
        byte[] b=new byte[2048];
        socket.getInputStream().read(b);
        return new String(b);

    }

    public String setnx(String key, String value) throws Exception {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("*3").append("\r\n");
        stringBuffer.append("$5").append("\r\n");
        stringBuffer.append("setnx").append("\r\n");
        stringBuffer.append("$").append(key.getBytes().length).append("\r\n");
        stringBuffer.append(key).append("\r\n");
        stringBuffer.append("$").append(value.getBytes().length).append("\r\n");
        stringBuffer.append(value).append("\r\n");
        socket.getOutputStream().write(stringBuffer.toString().getBytes());
        byte[] b = new byte[2048];
        socket.getInputStream().read(b );
        return new String(b);
    }

    // 管道
    public void pipeline(String key)throws Exception {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("*2").append("\r\n");
        stringBuffer.append("$"+CommandRedis.subscribe.name().length()).append("\r\n");
        stringBuffer.append(CommandRedis.subscribe).append("\r\n");
        stringBuffer.append("$").append(key.getBytes().length).append("\r\n");
        stringBuffer.append(key).append("\r\n");
        socket.getOutputStream().write(stringBuffer.toString().getBytes());
        InputStream inputStream = socket.getInputStream();
        while (true) {
            byte[] b = new byte[2048];
            inputStream.read(b );
            System.out.println(new String(b));
        }

    }

    //subscribe
    public void subscribe(String key)throws Exception {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("*2").append("\r\n");
        stringBuffer.append("$"+CommandRedis.subscribe.name().length()).append("\r\n");
        stringBuffer.append(CommandRedis.subscribe).append("\r\n");
        stringBuffer.append("$").append(key.getBytes().length).append("\r\n");
        stringBuffer.append(key).append("\r\n");
        socket.getOutputStream().write(stringBuffer.toString().getBytes());
        InputStream inputStream = socket.getInputStream();
        while (true) {
            byte[] b = new byte[2048];
            inputStream.read(b );
            System.out.println(new String(b));
        }
    }

    public void close(){
        if(socket != null){
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
public enum CommandRedis {

    set,get,incr,subscribe

}
  • 分片

    > RedisClient分片方式,简单模拟,理解概念分片。

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TestRedisClient {
    public static void main(String[] args) throws IOException {

 /*       RedisClient redisClient=new RedisClient();
        System.out.println(redisClient.set("wk","悟空"));
        System.out.println(redisClient.get("wk"));*/


        List<RedisClient> pool=new ArrayList<>();
        pool.add(new RedisClient("192.168.0.12",6379));
        pool.add(new RedisClient("192.168.0.12",6380));
        pool.add(new RedisClient("192.168.0.12",6381));
        Crc16Sharding crc16Sharding=new Crc16Sharding(pool);
        for (int i=0;i<100;i++){
            String key="xx"+i;

            RedisClient redisClient=crc16Sharding.crc16(key);
            redisClient.set(key,i+"");
            System.out.println(redisClient.get(key));
        }

    }
}
import com.sun.org.apache.xerces.internal.impl.xpath.regex.Match;
import java.util.List;

public class Crc16Sharding {
    List<RedisClient> pool;

    public Crc16Sharding(List<RedisClient> pool) {
        this.pool = pool;
    }

    /**
     * 通过一个key可以定位到一块 节点
     * @param key
     * @return
     */
    public RedisClient crc16(String key){

        int num=Math.abs(key.hashCode()%pool.size());
        return  pool.get(num);
       /* if(key.length()<3){
           return pool.get(0);
        }else  if(key.length()<6){
            return  pool.get(1);
        }else{
            return  pool.get(2);
        }*/
    }
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TestRedisClient {
    public static void main(String[] args) throws IOException {
        List<RedisClient> pool=new ArrayList<>();
        pool.add(new RedisClient("192.168.0.12",6379));
        pool.add(new RedisClient("192.168.0.12",6380));
        pool.add(new RedisClient("192.168.0.12",6381));
        Crc16Sharding crc16Sharding=new Crc16Sharding(pool);
        for (int i=0;i<100;i++){
            String key="xx"+i;

            RedisClient redisClient=crc16Sharding.crc16(key);
            redisClient.set(key,i+"");
            System.out.println(redisClient.get(key));;
        }
    }
}

(四)redis使用技巧

  1. 如果是订单表,取的话也是通过唯一的订单号来进行,不要通过循环去redis里面取。
  2. 开关类型的放到本地的jvm内存中,尽量减少redis的压力。
  3. 避免使用慢查询 hgetall
  4. 存储redis的购物车,有的人都是很多的好几M的,几百个商品,redis存储的内容的压缩。减少通信的宽带。优化存储内容。
  5. 少用字符串存储,可以存储map格式放入redis。获取redis里面的map,直接通过key就可以取到对应的值。

(五)监控&运维

  • Open-falcon

    > http://open-falcon.org/

    >open-falcon是小米开源监控系统,强大灵活的数据采集、采集、传输、绘制、查询、报警等。采用全部golang编写,portal和dashboard使用 python 编写。

『互联网架构』软件架构-redis的通信协议(protocol)(52)

『互联网架构』软件架构-redis的通信协议(protocol)(52)

  • Redis-migrate-tool

    >https://github.com/vipshop/redis-migrate-tool

    >2年多没更新了,可以了解下

    >Redis-migrate-tool是唯品会开源针对redis数据运维工具。

    支持单独、twemproxy集群、redis custer、aof、rdb文件迁移。支持实时迁移、异构迁移、过滤等功能。

PS:介绍了运维工具,redis通信的内容拼接,redis存储的技巧,redis正常的时候没问题,并发量大的时候一定要注意,在大流量的情况下,代码的细节至关重要!

百度未收录

>>原创文章,欢迎转载。转载请注明:转载自IT人故事会,谢谢!

>>原文链接地址:上一篇:

已是最新文章


以上所述就是小编给大家介绍的《『互联网架构』软件架构-redis的通信协议(protocol)(52)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Alone Together

Alone Together

Sherry Turkle / Basic Books / 2011-1-11 / USD 28.95

Consider Facebookit’s human contact, only easier to engage with and easier to avoid. Developing technology promises closeness. Sometimes it delivers, but much of our modern life leaves us less connect......一起来看看 《Alone Together》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具