内容简介:redis的通信协议是什么?双方约定了一种编码方式,客户端将要发送的命令进行编码,然后服务端收到后,使用同样的协议进行解码,服务端处理完成后,再次编码返回给客户端,客户端解码拿到返回结果,这样就完成了一次通信。
redis的通信协议是什么?双方约定了一种编码方式,客户端将要发送的命令进行编码,然后服务端收到后,使用同样的协议进行解码,服务端处理完成后,再次编码返回给客户端,客户端解码拿到返回结果,这样就完成了一次通信。
(一)协议介绍
https://redis.io/topics/protocol
- 易于实现
- 可以高效地被计算机分析(parse)
- 可以很容易地被人类读懂
(二)编码后的字符标记解释
- 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 “*” 数组
(三)模拟 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使用技巧
- 如果是订单表,取的话也是通过唯一的订单号来进行,不要通过循环去redis里面取。
- 开关类型的放到本地的jvm内存中,尽量减少redis的压力。
- 避免使用慢查询 hgetall
- 存储redis的购物车,有的人都是很多的好几M的,几百个商品,redis存储的内容的压缩。减少通信的宽带。优化存储内容。
- 少用字符串存储,可以存储map格式放入redis。获取redis里面的map,直接通过key就可以取到对应的值。
(五)监控&运维
-
Open-falcon
> http://open-falcon.org/
>open-falcon是小米开源监控系统,强大灵活的数据采集、采集、传输、绘制、查询、报警等。采用全部golang编写,portal和dashboard使用 python 编写。
-
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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 『互联网架构』软件架构-解密电商系统-互联网BAT商品详情缓存架构(82)
- 『互联网架构』软件架构-分布式架构(14)
- 『互联网架构』软件架构-电商系统架构(上)(69)
- 『互联网架构』软件架构-电商系统架构(中)(70)
- 『互联网架构』软件架构-电商系统架构(下)(71)
- 『互联网架构』软件架构-电商系统架构发展历程(68)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Base64 编码/解码
Base64 编码/解码
RGB CMYK 转换工具
RGB CMYK 互转工具