zoukankan      html  css  js  c++  java
  • Redis 介绍

    1、简介

      Redis 是一款开源的,基于 BSD 许可的,高级键值 (key-value) 缓存 (cache) 和存储 (store) 系统。由于 Redis 的键包括 string,hash,list,set,sorted set,bitmap 和 hyperloglog,所以常常被称为数据结构服务器。

      为了满足高性能,Redis 采用内存 (in-memory) 数据集 (dataset)。根据你的使用场景,你可以通过每隔一段时间转储数据集到磁盘,或者追加每条命令到日志来持久化。持久化也可以被禁用,如果你只是需要一个功能丰富,网络化的内存缓存。

      Redis 还支持主从异步复制,非常快的非阻塞初次同步、网络断开时自动重连局部重同步。

      Redis特点:
        1、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
        2、Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,sorted set,hash等数据结构的存储。
        3、Redis支持数据的备份,即master-slave模式的数据备份。
      Redis优势:
        1、性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
        2、丰富的数据类型 – Redis支持二进制案例的 String, List, Hash, Set 及 Sorted Set 数据类型操作。
        3、原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
        4、丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性
    2、多数据类型
    • String
    • List
    • Set
    • Hash
    • Sorted Set

    3、持久化

      redis支持两种持久化方式,一种是 RDB(快照)也是默认方式,另一种是Append-only file(aof)的方式。

      3.1 快照RDB

      快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照。也可以命令行的方式让redis进行snapshotting。

      快照生成过程大致如下:
      redis调用fork出父子进程,父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照;当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。
      快照(snapshotting)不足之处在于两次快照操作之间是有时间间隔的,一旦数据库出现问题,那么快照文件中保存的数据并不是全新的,从上次快照文件生成到Redis停机这段时间的数据全部丢掉了。
      3.2 aof方式
      比上面所说的快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
      可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次):
      1、appendonly yes //启用aof持久化方式
      2、appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
      3、appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
      4、appendfsync no //完全依赖os,性能最好,持久化没保证
      aof方式的持久化也还是有可能会丢失部分修改,因为os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。另外aof 的方式可能会导致持久化文件会变的越来越大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。
      bgrewriteaof命令执行过程如下:
      redis调用fork出父子两个进程,子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令;
      父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题;
      当子进程把快照内容写入以命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件;
      现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

    4、内存管理

      4.1 Redis对象

      所有的Redis对象都被封装在RedisObject这个结构体当中,如下:

    typedef struct redisObject {
        unsigned type,           // 4字节,数据类型(String,List,Set,Hash,Sorted Set)
        unsigned encoding,   // 4字节,编码方式
        unsigned lru,              // 24字节
        int refcount,               // 对象引用计数
        void *ptr                    // 数据具体存储的指向
    } robj;

      Redis 内部使用一个 redisObject 对象来表示所有的 key 和 value,type 代表一个 value 对象具体是何种数据类型,encoding 是不同数据类型在 redis 内部的存储方式,比如:type=string 代表 value 存储的是一个普通字符串,那么对应的 encoding 可以是 raw 或者是 int,如果是 int 则代表实际 redis 内部是按数值型类存储和表示这个字符串的。

      4.2 内存淘汰策略

      Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:

    •   noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
    •   allkeys-lru:在主键空间中,优先移除最近未使用的key。
    •   volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
    •   allkeys-random:在主键空间中,随机移除某个key。
    •   volatile-random:在设置了过期时间的键空间中,随机移除某个key。
    •   volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除

    5、主从同步

      Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架构。

      Redis主从复制的一些特点:
      1.master可以有多个slave
      2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构
      3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。
      4.主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余
      5.可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然后只在slave上配置数据持久化。
      Redis主从复制的过程:

       当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。
      redis的主从复制策略是通过其持久化的rdb文件来实现的,其过程是先dump出rdb文件,将rdb文件全量传输给slave,然后再将dump后的操作实时同步到slave中。
      1、Slave端在配置文件中添加了slaveof指令,于是Slave启动时读取配置文件,初始状态为REDIS_REPL_CONNECT;
      2、Slave端在定时任务serverCron中连接Master,发送sync命令,然后阻塞等待master发送回其内存快照文件(最新版的Redis已经不需要让Slave阻塞);
      3、Master端收到sync命令简单判断是否有正在进行的内存快照子进程,没有则立即开始内存快照,有则等待其结束,当快照完成后会将该文件发送给Slave端;
      4、Slave端接收Master发来的内存快照文件,保存到本地,待接收完成后,清空内存表,重新读取Master发来的内存快照文件,重建整个内存表数据结构,并最终状态置位为 REDIS_REPL_CONNECTED状态,Slave状态机流转完成;
      5、Master端在发送快照文件过程中,接收的任何会改变数据集的命令都会暂时先保存在Slave网络连接的发送缓存队列里(list数据结构),待快照完成后,依次发给Slave,之后收到的命令相同处理,并将状态置位为 REDIS_REPL_ONLINE。

    6、事物机制:

      Redis事务通常会使用MULTI,EXEC,WATCH等命令来完成,redis的事务不支持回滚,事务执行时会阻塞其它客户端的请求执行。
      Redis事务从开始到结束通常会通过三个阶段:1、事务开始 2、命令入队 3、命令执行。
      与实务相关的状态标识flag,用于标识当前客户端的事物状态,如下: 
    #define REDIS_MULTI (1<<3)  
    #define REDIS_DIRTY_EXEC (1<<12)
    #define REDIS_DIRTY_CAS (1<<5)

    7、应用场景

      1、session会话共享缓存

      2、数据缓存

      3、队列:1)Redis自带的PUB/SUB机制,即发布-订阅模式。2)Redis的PUSH/POP机制,利用的Redis的列表(lists)数据结构。比较好的使用模式是,生产者lpush消息,消费者brpop消息,并设定超时时间,可以减少redis的压力。

    Redis 命令参考Doc

  • 相关阅读:
    10 个深恶痛绝的 Java 异常。。
    为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
    推荐一款代码神器,代码量至少省一半!
    Spring Cloud Greenwich 正式发布,Hystrix 即将寿终正寝。。
    hdu 3853 LOOPS(概率 dp 期望)
    hdu 5245 Joyful(期望的计算,好题)
    hdu 4336 Card Collector(期望 dp 状态压缩)
    hdu 4405 Aeroplane chess(概率+dp)
    hdu 5036 Explosion(概率期望+bitset)
    hdu 5033 Building (单调栈 或 暴力枚举 )
  • 原文地址:https://www.cnblogs.com/kingsonfu/p/10407413.html
Copyright © 2011-2022 走看看