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. php 路途一点启示

    wo:  面试了很多说后台不适合女孩,我不相信,而且我还很笨 he:不是立马就能让别人认可你,其中过程要经历很多得,有时候也要换个方式的'' wo: 我只是想用学的知识得到实践 he:那学习的过程不是 ...

  2. selenium配置Chrome驱动

    1.http://chromedriver.storage.googleapis.com/index.html   chrome下载驱动地址 和对应的版本驱动,不用FQ 2.配置方法:如在e盘创建一个 ...

  3. IDEA能运行,但是出现红色下划线的问题报 cannot resolve method

    能编译通过并运行说明SDK导入正确,但是为啥我们点击每一个Java文件会出现好多红色的下划线 ,并提示idea cant resolve symbol.原因就是可能没有清除原来的历史缓存,导致一些错误 ...

  4. 【微信公众号开发】【8】网页授权获取用户基本信息(OAuth 2.0)

    前言: 1,在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名. 请注意,这 ...

  5. input事件在ie9以下不兼容问题完美解决

    上周四好不容易加了几天班把刚接手的一个pc页面做完,周五同事说要兼容ie7~ie9,结果在上面一跑,输入都没法输入. 我的需求是用6个span作为虚拟的密码输入框,实际上是用一个藏在页面里的input ...

  6. python low版线程池

    1.low版线程池设计思路:运用队列queue 将线程类名放入队列中,执行一个就拿一个出来import queueimport threading class ThreadPool(object): ...

  7. PostgreSQL进程和内存结构

    PostgreSQL数据库启动时,会先启动一个叫做Postmaster的主进程,还会fork一些辅助子进程,这些辅助子进程各自负责一部分功能,辅助子进程分类如下: $ ps -ef | grep po ...

  8. loj 10117 简单题(cqoi 2006)

    题目来源:CQOI 2006 有一个 n 个元素的数组,每个元素初始均为 0.有 m条指令,要么让其中一段连续序列数字反转——0变 1,1 变 0(操作 1),要么询问某个元素的值(操作 2). 例如 ...

  9. JavaScript中var和this定义变量的区别

    JavaScript中var和this定义变量的区别 在js中声明变量时可以使用var和this,但使用this的有很大一部分参考书是没有的,经过查阅相关资料总结如下: 用var和this声明变量,存 ...

  10. iOS 强大第三方资源库

    Github用法 git-recipesGit recipes in Chinese. 高质量的Git中文教程. lark怎样在Github上面贡献代码 my-git有关 git 的学习资料 giti ...