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

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

内容简介: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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

设计沟通十器

设计沟通十器

Daniel M. Brown / 樊旺斌 / 机械工业出版社 / 2008-12 / 49.00元

本书提供了网站设计时所需的可交付文档资料包括:概念模型,站点地图,可用性报告等,这些文档资料是设计人员和客户进行交流的主要工具。本书深入讨论了文档推介和风险规避技巧,向你展示了如何将文档资料按要求制作成有效的交流工具。 本书内容全面,结构清晰,讲解详细。可作为网站设计人员的参考用书。 关于网站设计的多数讨论好像都着眼于流程的创建,然而,要想把概念变为现实,需要一整套强大的可交付文档资料......一起来看看 《设计沟通十器》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具