Overview

  • 内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。
  • redis底层数据结构:跳跃表 [为什么选skiplist而不是red-black tree]
  • 支持多种数据结构:String, hash, list, set, sorted set...
  • 内置: Replication, lua scripting, LRU eviction, transaction, persistence, Sentinel, Cluster. [具体往下看,分别有具体介绍~]

单线程效率

  • 完全基于内存

  • 数据结构简单,对数据操作也简单

  • 多路IO复用模型 (参考link.)

  • 不要考虑各种锁

  • 不存在多线程上下文切换而消耗CPU

事务

  • 事务是一个单独的隔离操作,事务中所有命令都会序列化、按顺序地执行,执行过程中不被其它客户端发来的命令请求打断。
  • 不支持rollback (redis认为失败的命令是由编程错误造成,不应出现在生产环境中;使redis内部保持简单且快速。)
  • 若事务中某些命令在执行时产生了错误,事务中的其他命令仍然会继续执行。
  • redis中关于事务的命令:MULTI、EXEC、DISCARD、WATCH

CAS乐观锁

  • watch命令可以为redis事务提供CAS(check-and-set)行为。
  • 典型的例子如下:
    val = GET mykey
    val = val + 1
    SET mykey $val

    上述代码在多个client争用时会产生不正确的结果。可以通过watch来解决:

    WATCH mykey
    val = GET mykey
    val = val + 1
    MULTI
    SET mykey $val
    EXEC

    上述代码会在exec执行之前监视mykey,如果有其他client修改了mykey的值,那么当前client的事务就会失败。程序要做的就是不断重试该操作,直到没有发生碰撞为止。
    watch命令从其被调用开始生效,一直到调用EXEC为止。

  • 实际上这就是乐观锁。(通常情况下不会产生大量的重试。)

ACID

以上,redis事务

  • 不满足原子性:redis事务在执行过程遇到错误,不会回滚,而是继续执行后续命令。

  • ?持久性:redis没有在事务层面有额外的持久性保证,所以仍然由redis提供的持久化模式决定。 [所以redis事务是不能保证持久性的,除非底层是aof always的持久化模式。]

  • 隔离性:redis事务执行过程中,不会处理其他命令。

  • 一致性:能保证。

Persistence

  • bgsave做全量持久化:耗时长,不够实时,宕机时存在大量数据丢失。

    • bgsave的原理是什么?你给出两个词汇就可以了,fork和cow。

    • fork是指redis通过创建子进程来进行bgsave操作。

    • cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。 [使用单独子进程来进行持久化,主进程不进行任何IO操作,保证了redis的高性能。 ]

    • 由于os的写时复制(copy on write)机制,父子进程会共享当前的物理页面,当父进程处理写请求时,os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照。
    • [注意:每次快照持久化都是将内存数据完整地写入到磁盘一次,并不是增量的。因而,在数据量比较大的时候必然会引起大量的磁盘IO。]
  • aof(Append-only file)做增量持久化: 将“操作+数据”以格式化指令的方式追加到操作日志文件的尾部。在append操作返回后才进行实际的数据变更。

  • —> 二者结合,在redis实例重启时,会使用bgsave持久化文件重新构建内存,再使用aof重放近期的操作指令来实现完整恢复重启之前的状态。

  • 突然断电的情况? —> 取决于aof的配置:如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。 [linux文件操作的“延迟写入”:并非每次write都会出发实际磁盘操作,而是进入buffer] aof记录同步选项如下

    • always:每一条aof记录都立即同步到文件,最安全的方式,但带来更多的磁盘操作和更大的阻塞延迟。

    • erverysec:每秒同步一次。如果遇到物理server故障,可能导致最近1s内aof记录丢失。

    • no:redis并不直接调用文件同步(并不是说不采用aof),而是交给os来处理 --> os可以根据buffer填充/通道空闲时间等择机触发同步。性能比较好,数据丢失量会与OS配置有关。

以上,可以看出来redis并不十分适合“所有数据都需要机器可靠”的场景(may be relational db for ur choice)

  • RDB: 在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
  • 默认的持久化方式
  • 优点:
    • 使用单独子进程来进行持久化,主进程不进行任何IO操作,保证了redis的高性能。
    • 恢复速度快。
  • 缺点:
    • 间隔一段时间进行持久化,容易发生数据丢失。
    • 每次保存RDB时,redis都要fork出一个子进程,在数据集比较大时,fork可能会十分耗时,造成server在一段时间内停止处理client请求。

Partition

  • 按key分区
  • 作用:
    • 增大内存
    • 通过增加计算机来提高redis计算能力、网络带宽
  • 分区方式:
    • range:需要一张表存储数据到redis实例的映射关系。
    • hash:key必须是object_name:<id>的形式。
  • 分区实现方式:
    • 客户端分区:在client端就已经决定数据会被存储到哪个redis节点或从哪个redis节点读取。
    • 代理分区:client将请求发给代理,然后代理决定。redis和memcached的一种代理实现就是Twemproxy
    • 查询路由(Querying routing):client随即地请求任意一个redis实例,然后由redis将请求转发给正确的redis节点。
      Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求转发给正确的redis节点,而是在client端的帮助下直接redirected到正确的redis节点。
  • 缺点:
    • 涉及多个key的操作不被支持
    • 同时操作多个key,不能使用redis事务
    • 分区粒度是key,so it is not possible to shard a dataset with a single huge key like a very big sorted set
    • 分区时的动态扩容或缩容可能非常复杂。

Redis集群

Sentinel

  • redis sentinel着眼于高可用,在master宕机时会自动提升slave

  • Sentinel本身也是集群,避免SPOF。redis的客户端可以随意地连接任意一个sentinel来获得关于redis集群中的信息。 (sentinel集群自身也需要多数机制,也就是2个sentinel进程时,挂掉一个另一个就不可用了。)

  • sentinel的failover过程对client 是透明的。

    Set sentinels = new HashSet();
    sentinels.add(new HostAndPort("172.30.37.73", 26379).toString());
    sentinels.add(new HostAndPort("172.30.37.73", 26380).toString());
    sentinels.add(new HostAndPort("172.30.37.73", 26381).toString());
    JedisSentinelPool sentinelPool = new JedisSentinelPool("myredis", sentinels);
    System.out.println("Current master: " + sentinelPool.getCurrentHostMaster().toString()); Jedis master = sentinelPool.getResource();
    master.set("username","tom");
    sentinelPool.returnResource(master);

Redis Cluster

  • redis cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。 [Sharding]

  • Redis采取了P2P而非Proxy方式、异步复制、客户端重定向等设计,而牺牲了部分的一致性。

  • 可用性:在Cluster推出之前,可用性要靠Sentinel保证。有了集群之后也自动具有了Sentinel的监控和自动Failover能力。

  • 有了Cluster功能后,Redis从一个单纯的NoSQL内存数据库变成了分布式NoSQL数据库,CAP模型也从CP变成了AP

  • redis cluster VS codis

    • redis cluster基于smart client和无中心的设计,client必须按key的哈希将请求直接发送到对应的节点。 [转发] —> client不能直接像单机一样使用pipeline来提高效率,想同时执行多个请求来提速必须在client端自行实现异步逻辑。

    • 而codis因其有中心节点、基于proxy的设计,对client来说可以像对单机redis一样去操作proxy(除了一些命令不支持),还可以继续使用pipeline并且如果后台redis有多个的话速度会显著快于单redis的pipeline。

    • codis是一整套解决方案,还提供了auto-rebalance(迁移对上层业务透明)等。

redis pipelining

  • Redis is a TCP server using the client-server model and what is called a Request/Response protocol.

  • The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response.

Operations

  • keys VS scan

    • keys阻塞 [redis单线程]

    • scan非阻塞,但有一定重复概率

FYI

[Go back to REDIS]的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  3. mac osx 安装redis扩展

    1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis   ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...

  4. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  5. Redis数据库

    Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...

  6. redis 学习笔记(2)

    redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...

  7. redis 学习笔记(1)

    redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...

  8. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  10. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

随机推荐

  1. oracle导出导入指定表

    从源数据库导出: exp user1/pwd@server1/orcl file=c:\temp\exp.dmp tables=(table1, table2) 导入到目标数据库: imp user2 ...

  2. C#计算两个时间年份月份差

    C#计算两个时间年份月份差 https://blog.csdn.net/u011127019/article/details/79142612

  3. 51Nod 1058 N的阶乘的长度

    输入N求N的阶乘的10进制表示的长度.例如6! = 720,长度为3.   Input 输入N(1 <= N <= 10^6) Output 输出N的阶乘的长度 Input示例 6 Out ...

  4. button theme

    children:[ButtonTheme.bar( child:ButtonBar( children:[ FlatButton... ], ),), ]

  5. Html img 标签

    Html img 标签 <html> <body> <!-- img 标签用于显示图片.src="xxx.jpg" 指定图片路径名称--> &l ...

  6. --save 与--save-dev的区别

    一.模式 运行webpack命令时,一定要指定模式. webpack --mode developmentwebpack --mode production二.--save -dev --save:将 ...

  7. git 管理和存储二进制大文件

    git 管理二进制文件 本文档将逐步带你体验 git 的大文件管理方式. 环境: windows10 64位 cmd git版本: git version 2.18.0.windows.1 创建到推送 ...

  8. android to hide the keybord

    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hi ...

  9. 《温故而知新》JAVA基础五

    定义:是类和类之间的关系"is a" 弗父类(基类)->子类(派生类) 是一直单继承的关系 好处:子类拥有父类的属性方法(private除外) 语法 class Son ex ...

  10. variable 'o' used without having been completely initialized Compiling Vertex program

    variable 'o' used without having been completely initialized Compiling Vertex program   v2f vert (ap ...