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. 第六篇——Struts2的后缀

    Struts2后缀 1.Struts2默认后缀是action: 2.Struts2使用默认后缀时 *.aciton 和 * 都是同一个请求: 3.Struts2自定义后缀后只能使用自定义的后缀访问: ...

  2. spring 的web.xml

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java ...

  3. JDK1.7安装和配置及注意事项

    要求 必备知识 windows 7 基本操作. 运行环境 windows 7 下载地址 环境下载 下载JDK 下载地址:http://www.oracle.com/technetwork/java/j ...

  4. IVIEW对的table组件超出长度用省略号代替,使用气泡提示。

    render: (h, params) => { return h('div', [ h('Tooltip', { props: { placement: 'top' } }, [ h('spa ...

  5. tp剩余未验证内容-7

    bash脚本中 的 set -e表示 exit immediately if a simple command returns a non-zero value.主要是为了防止错误被忽略.会被立即退出 ...

  6. Postman接口调试神器

    Postman起初源自googleBrowser的一款插件,现已经有单独软件,当然之前的插件也存在  它主要是用于接口的的调试 接口请求的流程 一.GET请求 GET请求:点击Params,输入参数及 ...

  7. 5、zabbix使用进阶(01)

    详细描述user parameters.定义主机发现规则实现自动发现.如何定义和实现自动注册方式 zabbix常用术语 1.主机(host):要监控的网络设备,可有IP或DNS名称指定: 2.主机组( ...

  8. jQuery学习笔记(一)

    jQuery 事件 - ready() 方法 实例 在文档加载后激活函数(): $(document).ready(function(){ $(".btn1").click(fun ...

  9. ORM模型

    一.创建及映射(orm_intro_demo文件) 在项目新建App下的models.py文件下新建ORM模型: from django.db import models #如果要将一个普通的类变成一 ...

  10. 个人爱好:idea 项目结构呈现风格