zoukankan      html  css  js  c++  java
  • <Redis Advance><Pipelining><Memory Optimization><Expire><Transactions>

    Overview

    • About Redis pipelining
    • About Redis memory optimization
    • About Redis expire
    • About Redis transactions

    Pipelining

    Request/Response protocols and RTT

    • Redis is a TCP server using the client-server model and what is called a Request/Response protocol.
    • This means that usually a request is accomplished with the following steps:
      • The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response.
      • The server processes the command and sends the response back to the client.
    • Clients and servers are connected via a networking link. Such a link can be very fasr(a loopback interface) or very slow(a connection established over the Internet with many hops between two hosts). 
    • The time is called RTT(Round Trip Time). This will affect the performances when a client needs to perform many requests in a row. [当客户端需要在一个批处理中执行多次请求时,RTT就会对性能产生较大的影响。] 比如说,假设RTT时间很长,250ms,这时候即使服务器每秒能处理100k的请求数,我们每秒也只能处理4个请求。
    • If the interface used is a loopback interface, the RTT is much shorter(for instance my host reports 0.044ms pinging 127.0.0.1), but it is still a lot if u need to perform many writes in a row.

    Redis Pipelining

    • A Request/Response server can be implemented so that it is able to process new requests even if the client didn't already read the old responses. [服务器能够在旧的请求还未被响应的情况下处理新的请求,那么就可以将多个命令发送到服务器,而不用等待回复,直接在最后一个步骤中读取该回复即可。]

    Summary

    • so,如果不用管道,四个请求需要8个TCP报文,4次RTT。如果网络延迟0.125s,那么需要1s完成四个请求。redis的处理能力完全发挥不出来。
    • 为了提高效率,处理利用mset、mget之类的单条命令处理多个key外,
    • 我们还可以使用pipelining的方式,从client打包多条命令,一起发出,不需要等待单条命令的响应返回,redis server会处理完多条命令后将结果打包返回给client。
    • 假设tcp报文不会因为过长而被拆分,上述4个请求就只需要两个tcp报文。
    • 但是也不是说打包的命令越多越好,因为打包的命令越多,内存消耗也越多。因为redis必须在处理完所有命令前缓存之前所有命令的处理结果。

     Test

    • public void pipeLine() {
              Jedis jedis = null;
              try {
                  jedis = new Jedis(REDIS_HOST, REDIS_PORT);
                  Pipeline pipeline = jedis.pipelined();
                  for (int i = 0; i < COUNT; i++) {
                      pipeline.incr(testKey);
                  }
                  pipeline.sync();
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  if(jedis != null) jedis.disconnect();
              }
      
          }
      
          public void withoutPipeline() {
              Jedis jedis = null;
              try {
                  jedis = new Jedis(REDIS_HOST, REDIS_PORT);
                  for (int i = 0; i < COUNT; i++) {
                      jedis.incr(testKey);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  if (jedis != null) jedis.disconnect();
              }
          }
      
          public static void main(String[] args) {
              PipelineTest pipelineTest = new PipelineTest();
              long start = System.currentTimeMillis();
      
              pipelineTest.withoutPipeline();
      
              long mid = System.currentTimeMillis();
              System.out.println("Without pipeline, using: " + (mid - start));
      
              pipelineTest.pipeLine();
      
              System.out.println("With pipeline, using: " + (System.currentTimeMillis() - mid));
      
          }
    • 输出:(100条incr请求)
      Without pipeline, using: 9816
      With pipeline, using: 45

    Memory Optimization

    Special encoding of small aggreagte data types

    • Redis2.2以后,存储集合数据的时候会采用内存压缩技术
    • 比如对Hash、List、Set以及Sorted Set,当这些集合中的所有数都小雨一个给定的元素,并且集合中元素数量小于某个值时,存储的数据会被以一种十分节省内存的方式进行编码。理论上能节省10倍以上内存。并且该编码技术对用户和redis api透明
    • 实质上是用CPU换内存。
    • 阈值可以在redis.conf中修改。

    Using 32 bit instances

    • 使用32bit的redis,那么对每个key将使用更少的内存。

    Bit and byte level operations

    • Redis2.2引入了位级别和字级别的操作:GETRANGE, SETRANGE, GETBIT, SETBIT。
    • 通过使用这些命令,你可以把redis的字符串当成一个随机读取的(字节)数组
    • 例子:如果用户的id是连续的整数,那么你可以使用bitmap位图来纪录用户的性别,可以直接操作在bit之上。

    Uses hashes when possible

    • 小的散列表(小是指散列表内部存储的对象少)使用的内存非常小。
    • TBD...

    Expire

    EXPIRE Key seconds

    • 超时后只有在对key执行DEL、SET或GETSET时才会清除。[?????]
    • 过期精度:从Redis2.6起,过期时间误差缩小到0-1ms。
    • Redis如何淘汰过期key:
      • Redis keys过期有两种方式:主动和被动方式。
      • 被动:当一些客户端尝试访问它们时,key会被发现并主动的过期。
      • 主动:Redis每10s:
        • 测试随机的20个key,进行相关过期检测;
        • 删除已过期的key;
        • 若有多于25%的key过期,则重复步骤1
      • 以上,这是一个平凡的概率算法。

    Redis Transactions

    Introduction

    • MULTI, EXEC, DISCARD,WATCH是redis事务相关的命令。
    • 事务可以一次执行多个命令,并且:
      • 事务是一个单独的隔离操作:事务中所有命令都会序列化、按顺序地执行。执行过程中,不会被其他client的请求打断。
      • 原子操作:要么全部执行,要么全部不执行。
    • EXEC:
      • EXEC负责触发并执行事务中的所有命令
      • 如果client在使用MULTI开启了一个事务之后,如果没有执行EXEC,那么事务中所有命令都不会执行。
    • 当使用AOF方式做持久化时,redis会使用单个write命令将事务写到磁盘中。然而,若此时redis server由于某些原因挂掉,那么可能只有部分事务命令会被成功写入到磁盘中。
    • 若在redis重启时发现AOF文件出现了这样的问题,那么它会退出,并汇报一个错误。

    为什么Redis不支持roll back

    • 这种做法的优点:
      • 因为不需要支持roll back,因此redis内部可以保持简单且快速。
      • redis命令只会因为错误的语法而失败(并且这些错误不能在入队时发现),或是因为命令用在了错误类型的key上。理论上这些错误应该在开发过程被发现。

    使用check-and-set乐观锁

    • WATCH命令可以为redis事务提高check-and-set(CAS)行为
    • TBD...
    满地都是六便士,她却抬头看见了月亮。
  • 相关阅读:
    【宋红康程序思想学习日记5】数组排序之冒泡法
    求割点 poj 1523
    网络流 poj 3308 最小割
    网络流最小割 POJ 3469
    网络流 POJ2112
    网络流 HDU 3605
    网络流HDU 2883
    网络流 最大流HDU 3549
    微信公众平台开发者中心服务器配置Token验证失败问题
    排列熵算法简介及c#实现
  • 原文地址:https://www.cnblogs.com/wttttt/p/7091647.html
Copyright © 2011-2022 走看看