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...

<Redis Advance><Pipelining><Memory Optimization><Expire><Transactions>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. HDOJ 1022 Train Problem

    两个数组存进出顺序,如果不同进栈,相同出栈.

  2. p1457 The Castle

    原图找最大的房间及房间数很容易.然后从左下到右上找拆的位置.拆掉再bfs一次找面积. #include <iostream> #include <cstdio> #includ ...

  3. android -------- Eclipse选择NDK路径时 “Not a valid NDK directory”

    在 Eclipse选择NDK路径时 出现 “Not a valid NDK directory”  这样的错误 解决方式1 在你安装的ndk的主目录下创建一个ndk-build空文件,然后重新打开对话 ...

  4. android-------开发常用框架汇总

    响应式编程 RxJava https://github.com/ReactiveX/RxJava RxAndroid https://github.com/ReactiveX/RxAndroid 消息 ...

  5. 十分钟搞定pandas内容

    目录 十分钟搞定pandas 一.创建对象 二.查看数据 三.选择器 十二.导入和保存数据 参考:http://pandas.pydata.org/pandas-docs/stable/whatsne ...

  6. leetcode-algorithms-8 String to Integer (atoi)

    leetcode-algorithms-8 String to Integer (atoi) Implement atoi which converts a string to an integer. ...

  7. 函数使用十:COMMIT

    1)DB_COMMIT    :                    DB层的COMMIT,很少用到,大S之前说过,忘了 2)BAPI_TRANSACTION_COMMIT:COMMIT WORK/ ...

  8. 不安装Oracle数据库使用plsqldevloper

    1.Oracle官网下载instantclient 解压到D:\zl\instantclient_11_2 2.配置环境变量 ORACLE_HOME = D:\zl\instantclient_11_ ...

  9. 时间序列(六): 炙手可热的RNN: LSTM

    目录 炙手可热的LSTM 引言 RNN的问题 恐怖的指数函数 梯度消失* 解决方案 LSTM 设计初衷 LSTM原理 门限控制* LSTM 的 BPTT 参考文献: 炙手可热的LSTM 引言 上一讲说 ...

  10. WINDOWS中, 如何查看一个运行中的程序是64位还是32位的

    转自:https://blog.csdn.net/dayday3923/article/details/78597453?locationNum=7&fps=1 方法一: 任务管理器法任务管理 ...