.redis数据类型概述

    String:字符串,该类型是二进制安全的,即可以包含任何数据,如jpg图片或者序列化的对象。注意:一个键最大能存储512MB。

示例:

redis 127.0.0.1:6379> SET name "runoob"             ——》OK

redis 127.0.0.1:6379> GET name                      ——》"runoob"

    Hash:散列,Redis hash是一个string 类型的field和value的映射表,hash 特别适合用于存储对象。每个 hash 可以存储 232 -1 键值对(40多亿)。

示例:

redis> HMSET myhash field1 "Hello" field2 "World"    ——》OK

redis> HGET myhash field1                            ——》"Hello"

redis> HGET myhash field2                            ——》"World"

    List: 列表,Redis列表是简单的字符串列表,按照插入顺序排序。可添加一个元素到列表的头部(左边)或者尾部(右边)。

示例:

redis> lpush runoob redis                            ——》(integer) 1

redis> lpush runoob mongodb                          ——》(integer) 2

redis> lrange runoob 0 10                           

1) redis                            

2) mongodb

                    


    Set: 集合,Redis的Set是string类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。sadd添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。smembers取出所有的元素。集合中最大的成员数为232-1(4294967295, 每个集合可存储40多亿个成员)。


hash存储最大值 redis redis一个hash能存多少field_redis

    Sorted Set: 有序集合,zset和set一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一doubl类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

hash存储最大值 redis redis一个hash能存多少field_Redis_02

类型

简介

特性

场景

String

二进制安全

可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M

几乎所有场景都适用

Hash

键值对集合,即编程语言中的Map类型

并且可以像数据库中update一个属性一样只修改某一项属性值

适合存储对象

List

链表(双向链表)

增删快,提供了操作某一段元素的API

1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列

Set

哈希表实现,元素不重复

1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作

1、共同好友 2、利用唯一性,统计访问网站的所有独立ip

ZSet

有序排列

数据插入集合时,已经进行天然排序

1、排行榜 2、带权重的消息队列

 

       特点:

    1.Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

    2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,Sortedset,hash等数据结构的存储。

    3.Redis支持数据的备份,即master-slave模式的数据备份。

 

.redis的配置

redis.conf 配置项说明如下:

1. Redis默认不是以守护进程的方式运行,使用yes启用守护进程

    daemonize no

2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定

    pidfile /var/run/redis.pid

3. 指定Redis监听端口,默认端口为6379

    port 6379

4. 绑定的主机地址

    bind 127.0.0.1

5.当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能

    timeout 300

6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose

    loglevel verbose

7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null

    logfile stdout

8. 设置数据库的数量,默认数据库为0,可以使用SELECT<dbid>命令在连接上指定数据库id

    databases 16

9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

    save <seconds> <changes>

    Redis默认配置文件中提供了三个条件:

    save 900 1

    save 300 10

    save 60 10000

    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大

    rdbcompression yes

11. 指定本地数据库文件名,默认值为dump.rdb

    dbfilename dump.rdb

12. 指定本地数据库存放目录

    dir ./

13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步

    slaveof <masterip> <masterport>

14. 当master服务设置了密码保护时,slav服务连接master的密码

    masterauth <master-password>

15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭

    requirepass foobared

16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

    maxclients 128

17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区

    maxmemory <bytes>

18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no

    appendonly no

19. 指定更新日志文件名,默认为appendonly.aof

    appendfilename appendonly.aof

20. 指定更新日志条件,共有3个可选值:

    no:表示等操作系统进行数据缓存同步到磁盘(快)

    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)

    everysec:表示每秒同步一次(折中,默认值)

    appendfsync everysec

21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)

    vm-enabled no

22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享

    vm-swap-file /tmp/redis.swap

23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0

    vm-max-memory 0

24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值

    vm-page-size 32

25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。

    vm-pages 134217728

26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4

    vm-max-threads 4

27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启

    glueoutputbuf yes

28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法

    hash-max-zipmap-entries 64

    hash-max-zipmap-value 512

29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)

    activerehashing yes

30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

    include /path/to/local.conf

 

.redis基本指令

1.Redis DEL 命令用于删除已存在的键。不存在的 key 会被忽略。


2.Redis DUMP 命令用于序列化给定 key ,并返回被序列化的值。如果 key 不存在,那么返回 nil。否则,返回序列化之后的值。


3.Redis EXISTS 命令用于检查给定 key 是否存在。若 key 存在返回 1 ,否则返回 0 。


4.Redis Expire 命令用于设置 key 的过期时间,key 过期后将不再可用。单位以秒计。

下表列出了常用的 redis String命令:

1

SET key value 设置指定 key 的值。  

2

GET key 获取指定key的值。

3

GETRANGE key start end 返回key中字符串值的子字符

4

GETSET key value将给定key的值设为value ,并返回key的旧值。

5

GETBIT key offset对key所储存的字符串值,获取指定偏移量上的位(bit)。

6

MGET key1 [key2..]获取所有(一个或多个)给定 key 的值。

7

SETBIT key offset value对key所储存的字符串值,设置或清除指定偏移量上的位(bit)。

8

SETEX key seconds value将值value关联到key,并将key的过期时间设为 seconds。

9

SETNX key value只有在 key 不存在时设置 key 的值。

10

SETRANGE key offset value用value参数覆写给定key所储存的字符串值,从偏移量offset开始。

11

STRLEN key返回key所储存的字符串值的长度。

12

MSET key value [key value ...]同时设置一个或多个 key-value 对。

13

MSETNX key value [key value ...] 同时设置一个或多个 key-value 对,当且仅当所有给定key都不存在。

14

PSETEX key milliseconds value这个命令和SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。

15

INCR key将 key 中储存的数字值增一。

16

INCRBY key increment将key 所储存的值加上给定的增量值(increment)。

17

INCRBYFLOAT key increment将key所储存的值加上给定的浮点增量值(increment) 。

18

DECR key将key 中储存的数字值减一。

19

DECRBY key decrementkey所储存的值减去给定的减量值(decrement) 。

20

APPEND key value如果 key已经存在并且是一个字符串, APPEND命令将指定的value追加到该 key原来值(value)的末尾。

应用场景:String是最常用的一种数据类型,普通key/value存储都可归为此。能表达3种类型:字符串、整数和浮点数。根据场景相互间自动转型,并且根据需要选取底层的承载方式,value内部以int、sds作为结构存储。int存放整型数据,sds存放字节/字符串和浮点型数据。

 

下表列出了 redis hash 基本的相关命令:

1

HDEL key field1 [field2] 删除一个或多个哈希表字段。

2

HEXISTS key field 查看哈希表key中,指定的字段是否存在。

3

HGET key field 获取存储在哈希表中指定字段的值。

4

HGETALL key 获取在哈希表中指定key的所有字段和值。

5

HINCRBY key field increment 为哈希表key中的指定字段的整数值加上增量increment 。

6

HINCRBYFLOAT key field increment为哈希表 key中的指定字段的浮点数值加上增量increment 。

7

HKEYS key 获取所有哈希表中的字段。

8

HLEN key 获取哈希表中字段的数量。

9

HMGET key field1 [field2] 获取所有给定字段的值

10

HMSET key field1 value1 [field2 value2 ]同时将多个 field-value (域-值)对设置到哈希表 key 中。

11

HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。

12

HSETNX key field value只有在字段field不存在时,设置哈希表字段的值。

13

HVALS key 获取哈希表中所有值。

14

HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的键值对。

应用场景:如我们要存储一个用户信息对象数据,包含以下信息:用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储。

第一种:将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,且在需要修改其中一项信息时,需把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

第二种:这个用户信息对象有多少成员就存成多少个key-value对,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费严重。第三种:Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的 Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了。

下表列出了list相关的基本命令:

1

BLPOP key1 [key2 ] timeout 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

2

BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

3

BRPOPLPUSH source destination timeout 从列表中弹出一个值,将弹出的元素插入另一列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

4

LINDEX key index 通过索引获取列表中的元素

5

LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素

6

LLEN key 获取列表长度

7

LPOP key 移出并获取列表的第一个元素

8

LPUSH key value1 [value2] 将一个或多个值插入到列表头部

9

LPUSHX key value 将一个值插入到已存在的列表头部

10

LRANGE key start stop 获取列表指定范围内的元素

11

LREM key count value 移除列表元素

12

LSET key index value 通过索引设置列表元素的值

13

LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

14

RPOP key 移除列表的最后一个元素,返回值为移除的元素。

15

RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回

16

RPUSH key value1 [value2] 在列表中添加一个或多个值

17

RPUSHX key value 为已存在的列表添加值

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

 

下表列出了 Redis Set基本命令:

1

SADD key member1 [member2] 向集合添加一个或多个成员

2

SCARD key 获取集合的成员数

3

SDIFF key1 [key2] 返回给定所有集合的差集

4

SDIFFSTORE destination key1 [key2] 返回给定所有集合的差集并存储在 destination 中

5

SINTER key1 [key2] 返回给定所有集合的交集

6

SINTERSTORE destination key1 [key2] 返回给定所有集合的交集并存储在 destination 中

7

SISMEMBER key member 判断 member 元素是否是集合key的成员

8

SMEMBERS key 返回集合中的所有成员

9

SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合

10

SPOP key 移除并返回集合中的一个随机元素

11

SRANDMEMBER key [count] 返回集合中一个或多个随机数

12

SREM key member1 [member2] 移除集合中一个或多个成员

13

SUNION key1 [key2] 返回所有给定集合的并集

14

SUNIONSTORE destination key1 [key2] 所有给定集合的并集存储在 destination 集合中

15

SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素

set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

下表列出了 redis Zset的基本命令:

1

ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数

2

ZCARD key 获取有序集合的成员数

3

ZCOUNT key min max 计算在有序集合中指定区间分数的成员数

4

ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment

5

ZINTERSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中

6

ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量

7

ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合成指定区间内的成员

8

ZRANGEBYLEX key min max [LIMIT offset count] 通过字典区间返回有序集合的成员

9

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员

10

ZRANK key member 返回有序集合中指定成员的索引

11

ZREM key member [member ...] 移除有序集合中的一个或多个成员

12

ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员

13

ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员

14

ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员

15

ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到底

16

ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序

17

ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序

18

ZSCORE key member 返回有序集中,成员的分数值

19

ZUNIONSTORE destination numkeys key [key ...] 计算给定的一个或多个有序集的并集,并存储在新的 key 中

20

ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)

Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的 是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

 

四.底层原理

            Redis是一种key/value型数据库,每个key和value都是使用对象表示的。比如,我们执行以下代码:redis>SET message "hello redis",其中的key是message,是一个包含了字符串"message"的对象。而value是一个包含了"hello redis"的对象。

类型常量

对象的名称

REDIS_STRING

字符串对象

REDIS_LIST

列表对象

REDIS_HASH

哈希对象

REDIS_SET

集合对象

REDIS_ZSET

有序集合对象

 

 

 

 

 

 

 

Redis中的一个对象的结构体表示如下:type表示了该对象的对象类型,即上面五个中的一个。但为了提高存储效率与程序执行效率,每种对象的底层数据结构实现都可能不止一种。encoding就表示了对象底层所使用的编码。

typedef struct redisObject {

    unsigned type:4;     // 对象类型     

    unsigned notused:2;  // 不使用(对齐位)

    unsigned encoding:4; // 对象底层所使用的编码

    unsigned lru:22;     // LRU 时间(相对于 server.lruclock)

    int refcount;        // 引用计数

    void *ptr;          // 指向对象的值

 } robj;


 //sdshdr结构体如下:

 struct sdshdr {

     unsigned int len;

   unsigned int free;

   char buf[];

  };

字符串对象的编码可以是int、raw或者embstr。如果一个字符串的内容可以转换为long,那么该字符串就会被转换成为long类型,对象的ptr就会指向该long,并且对象类型也用int类型表示。普通的字符串有两种,embstr和raw。如果字符串对象的长度小于39字节,就用embstr对象。否则用传统的raw对象。redis并未提供任何修改embstr的方式,即embstr是只读的形式。对embstr的修改实际上是先转换为raw再进行修改。

embstr的好处:1.embstr的创建只需分配一次内存,而raw为两次(一次为sds分配对象,另一次为objet分配对象,embstr省去了第一次)。2.相对地,释放内存的次数也由两次变为一次。3.embstr的objet和sds放在一起,更好地利用缓存带来的优势。

   扩容:当对字符串的操作完成后预期的串长度小于1M时,扩容后的buf数组大小=预期长度*2+1;若大于1M,则buf总是会预留出1M的free空间。

raw和embstr的区别可以用下面两幅图所示:

hash存储最大值 redis redis一个hash能存多少field_数据_03

hash存储最大值 redis redis一个hash能存多少field_数据_04

列表对象的编码可以是ziplist或者linkedlist。ziplist是一种压缩链表,它的好处是更能节省内存空间,因为它所存储的内容都是在连续的内存区域当中的。当列表对象元素不大,每个元素也不大的时候,就采用ziplist存储。对象结构中ptr所指向的就是一个ziplist。整个ziplist只需要malloc一次,它们在内存中是一块连续的区域。

hash存储最大值 redis redis一个hash能存多少field_hash存储最大值 redis_05

当数据量过大时,ziplist就不是那么好用了。为了保证存储内容在内存中的连续性,插入的复杂度是O(N),即每次插入都会重新进行realloc。linkedlist是一种双向链表。它的结构比较简单,节点中存放pre和next两个指针,还有节点相关的信息。当每增加一个node的时候,就需要重新malloc一块内存。

hash存储最大值 redis redis一个hash能存多少field_数据_06

哈希对象的底层实现可以是ziplist或者hashtable。ziplist中的哈希对象是按照key1,value1,key2,value2这样的顺序存放来存储的。当对象数目不多且内容不大时,这种方式效率是很高的。hashtable的是由dict这个结构来实现的,dict是一个字典,其中的指针dicht ht[2] 指向了两个哈希表。dicht[0] 是用于真正存放数据,dicht[1]一般在哈希表元素过多进行rehash的时候用于中转数据。dictht中的table用于真正存放元素了,每个key/value对用一个dictEntry表示,放在dictEntry数组中。

hash存储最大值 redis redis一个hash能存多少field_Redis_07

集合对象的编码可以是intset或者hashtable。intset是一个有序整数集合,里面存的为某种同一类型的整数。查找元素的复杂度为O(logN),但插入时不一定为O(logN),因为有可能涉及到升级(intset不支持降级操作)操作。比如当集合里全是int16_t型的整数,这时要插入一个int32_t,那么为了维持集合中数据类型的一致,那么所有的数据都会被转换成int32_t类型,涉及到内存的重新分配,这时插入的复杂度就为O(N)了。

hash存储最大值 redis redis一个hash能存多少field_Redis_08

hash存储最大值 redis redis一个hash能存多少field_hash存储最大值 redis_09

有序集合的编码可能两种,一种是ziplist,另一种是skiplist与dict的结合。

ziplist作为集合和作为哈希对象是一样的,member和score顺序存放。按照score从小到大顺序排列。skiplist是一种跳跃表,它实现了有序集合中的快速查找,在大多数情况下它的速度都可以和平衡树差不多。但它的实现比较简单,可以作为平衡树的替代品。

hash存储最大值 redis redis一个hash能存多少field_hash存储最大值 redis_10

每一列都代表一个节点,保存了member和score,按score从小到大排序。每个节点有不同的层数,这个层数是在生成节点的时候随机生成的数值。每一层都是一个指向后面某个节点的指针。这种结构使得跳跃表可以跨越很多节点来快速访问。

 

五.事务原理

1.Redis发布订阅

Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将新消息通过 PUBLISH 命令发送给频道channel1时,这个消息就会被发送给订阅它的客户端:

hash存储最大值 redis redis一个hash能存多少field_数据_11

hash存储最大值 redis redis一个hash能存多少field_redis_12

创建订阅频道redisChat:

redis 127.0.0.1:6379> SUBSCRIBE redisChat

                    ——》Reading messages... (press Ctrl-C to quit)

                    ——》1) "subscribe"

                    ——》2) "redisChat"

                    ——》3) (integer) 1

重新开启另外1个redis 客户端,然后在同一频道redisChat发布两次消息,订阅者就能接收到消息。

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"                                       ——》(integer) 1

redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"

                                                 ——》(integer) 1

订阅者的客户端会显示如下消息:

                            ——》1) "message"

                            ——》2) "redisChat"

                            ——》3) "Redis is a great caching technique"

                            ——》1) "message"

                            ——》2) "redisChat"

                            ——》3) "Learn redis by runoob.com"

序号

命令及描述

1

PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道。

2

PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态。

3

PUBLISH channel message 将信息发送到指定的频道。

4

PUNSUBSCRIBE [pattern [pattern ...]] 退订所有给定模式的频道。

5

SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息。

6

UNSUBSCRIBE [channel [channel ...]] 指退订给定的频道。

       channel的订阅关系,维护在reids实例级别,独立于redisDB的key-value体系。发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。

2.Redis事务

A.基本指令

   1). MULTI用于标记事务块的开始。Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列,这个命令的返回值总是OK。

   2). EXEC在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。这个命令的返回值是一个数组,其中的每个元素分别是原子化事务中的每个命令的返回值。当使用WATCH命令时,如果事务执行中止,那么EXEC命令就会返回一个Nil值。当使用WATCH命令时,只有当受监控的键没有被修改时,EXEC命令才会执行事务中的命令,这种方式利用了检查再设置(CAS)的机制。

    3). DISCARD清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。这个命令的返回值总是OK。如果使用了WATCH命令,那么DISCARD命令就会将当前连接监控的所有键取消监控。

   4). WATCH当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。命令的运行格式:WATCH key [key ...],这个命令的返回值是总是OK。

   5). UNWATCH清除所有先前为一个事务监控的键。这个命令的返回值总是OK。

Redis 事务可以一次执行多个命令,一个事务从开始到执行会经历以下三个阶段:开始事务;命令入队;执行事务。并且带有以下两个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到EXEC命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

B.redis的网络协议

       redis协议位于TCP层之上,即客户端和redis实例保持双工的连接,交互的都是序列化后的协议数据,redis处理命令的主要逻辑:redis服务器对命令的处理都是单线程的,但是I/O层面却面向多个客户端并发地提供服务,并发到内部单线程的转化通过多路复用框架来实现。

C.redis的持久化机制

    redis主要提供了两种持久化机制:RDB和AOF;

    RDB默认开启,会按照配置的指定时间将内存中的数据快照到磁盘中,创建一个dump.rdb文件,redis启动时再恢复到内存中。redis会单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。

    AOF以日志的形式记录每个写操作(读操作不记录),只需追加文件但不可以改写文件,redis启动时会根据日志从头到尾全部执行一遍以完成数据的恢复工作。包括flushDB也会执行。主要有两种方式触发:有写操作就写、每秒定时写(也会丢数据)。因为AOF采用追加的方式,所以文件会越来越大,针对这个问题,新增了重写机制,就是当日志文件大到一定程度的时候,会fork出一条新进程来遍历进程内存中的数据,每条记录对应一条set语句,写到临时文件中,然后再替换到旧的日志文件(类似rdb的操作方式)。默认触发是当aof文件大小是上次重写后大小的一倍且文件大于64M时触发;

    当两种方式同时开启时,数据恢复redis会优先选择AOF恢复。一般情况下,只要使用默认开启的RDB即可,因为相对于AOF,RDB便于进行数据库备份,并且恢复数据集的速度也要快很多。

D.服务与连接

序号

命令及描述

1

AUTH password 验证密码是否正确

2

ECHO message 打印字符串

3

PING 查看服务是否运行

4

QUIT 关闭当前连接

5

SELECT index 切换到指定的数据库

F.备份、恢复以及安全

SAVE 命令用于创建当前数据库的备份。该命令将在 redis 安装目录中创建dump.rdb文件。

redis 127.0.0.1:6379> SAVE                                   ——》OK

       如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取redis目录可以使用 CONFIG 命令,如下所示:

redis 127.0.0.1:6379> CONFIG GET dir

1) "dir"

2) "/usr/local/redis/bin"

    redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行。

127.0.0.1:6379> BGSAVE                ——》Background saving started

设置并显示密码:

127.0.0.1:6379> CONFIG set requirepass "runoob"                   ——》OK

127.0.0.1:6379> CONFIG get requirepass

                                                  ——》1) "requirepass"

                                                  ——》2) "runoob"

127.0.0.1:6379> AUTH "123456"                       ——》OK