Redis 教程 Java工程师学习知识点

章节目录

1. Redis 简介及安装

1.1 Redis 简介

Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
  • Redis 支持数据的备份,即 master-slave 模式的数据备份。

1.2 Redis 优势

  • 性能极高 – Redis 能读的速度是 110000 次 /s, 写的速度是 81000 次 /s 。
  • 丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作全并后的原子性执行。
  • 丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性。

1.3 Redis 与其他 key-value 存储有什么不同?

  • Redis 有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis 的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

  • Redis 运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样 Redis 可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

2. Redis 基础知识、数据类型、Keys 的操作命令

2.1 数据类型

Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 zset(sorted set:有序集合)。

2.2 Redis 键 (key)

Redis 键命令用于管理 redis 的键。

语法

Redis 键命令的基本语法如下:

redis 127.0.0.1:6379> COMMAND KEY_NAME

实例

redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> DEL runoobkey
(integer) 1

在以上实例中 DEL 是一个命令, runoobkey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0

2.2.1 Key 命令

1    DEL key
该命令用于在 key 存在时删除 key。
2    DUMP key 
序列化给定 key ,并返回被序列化的值。
3    EXISTS key 
检查给定 key 是否存在。
4    EXPIRE key seconds
为给定 key 设置过期时间。
5    EXPIREAT key timestamp 
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
6    PEXPIRE key milliseconds 
设置 key 的过期时间以毫秒计。
7    PEXPIREAT key milliseconds-timestamp 
设置 key 过期时间的时间戳(unix timestamp) 以毫秒计
8    KEYS pattern 
查找所有符合给定模式 (pattern) 的 key 。
9    MOVE key db 
将当前数据库的 key 移动到给定的数据库 db 当中。
10    PERSIST key 
移除 key 的过期时间,key 将持久保持。
11    PTTL key 
以毫秒为单位返回 key 的剩余的过期时间。
12    TTL key 
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
13    RANDOMKEY 
从当前数据库中随机返回一个 key 。
14    RENAME key newkey 
修改 key 的名称
15    RENAMENX key newkey 
仅当 newkey 不存在时,将 key 改名为 newkey 。
16    TYPE key 
返回 key 所储存的值的类型。

3. Redis 对不同数据类型的操作命令使用

3.1 String(字符串)

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象 。

string 类型是 Redis 最基本的数据类型,一个键最大能存储 512MB。

实例

redis 127.0.0.1:6379> SET name "runoob"
OK
redis 127.0.0.1:6379> GET name
"runoob"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 name,对应的值为 runoob

注意:一个键最大能存储 512MB。

3.2 Hash(哈希)

Redis hash 是一个键名对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

实例

127.0.0.1:6379> HMSET user:1 username runoob password runoob points 200
OK
127.0.0.1:6379> HGETALL user:1
1) "username"
2) "runoob"
3) "password"
4) "runoob"
5) "points"
6) "200"

以上实例中 hash 数据类型存储了包含用户脚本信息的用户对象。 实例中我们使用了 Redis HMSET, HGETALL 命令,user:1为键值。

每个 hash 可以存储 232 -1 键值对(40 多亿)。

3.3 List(列表)

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

实例

redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储 40 多亿)。

3.4 Set(集合)

Redis 的 Set 是 string 类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd 命令

添加一个 string 元素到,key 对应的 set 集合中,成功返回 1, 如果元素已经在集合中返回 0,key 对应的 set 不存在返回错误。

sadd key member

实例

redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob
  1. "rabitmq"
  2. "mongodb"
  3. "redis"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储 40 多亿个成员)。

3.5 zset(sorted set:有序集合)

Redis zset 和 set 一样也是 string 类型元素的集合, 且不允许重复的成员。

 

不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。

zset 的成员是唯一的, 但分数 (score) 却可以重复。

zadd 命令

添加元素到集合,元素在集合中存在则更新对应 score

zadd key score member 

实例

redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE runoob 0 1000
  1. "redis"
  2. "mongodb"
  3. "rabitmq"

4. Redis 核心配置分析

Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf。

你可以通过 CONFIG 命令查看或设置配置项。

语法

Redis CONFIG 命令格式如下:

redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME

实例

redis 127.0.0.1:6379> CONFIG GET loglevel
  1. "loglevel"
  2. "notice"

使用 * 号获取所有配置项:

实例

redis 127.0.0.1:6379> CONFIG GET *
  1. "dbfilename"
  2. "dump.rdb"
  3. "requirepass"
  4. ""
  5. "masterauth"
  6. ""
  7. "unixsocket"
  8. ""
  9. "logfile"
  10. ""
  11. "pidfile"
  12. "/var/run/redis.pid"
  13. "maxmemory"
  14. "0"
  15. "maxmemory-samples"
  16. "3"
  17. "timeout"
  18. "0"
  19. "tcp-keepalive"
  20. "0"
  21. "auto-aof-rewrite-percentage"
  22. "100"
  23. "auto-aof-rewrite-min-size"
  24. "67108864"
  25. "hash-max-ziplist-entries"
  26. "512"
  27. "hash-max-ziplist-value"
  28. "64"
  29. "list-max-ziplist-entries"
  30. "512"
  31. "list-max-ziplist-value"
  32. "64"
  33. "set-max-intset-entries"
  34. "512"
  35. "zset-max-ziplist-entries"
  36. "128"
  37. "zset-max-ziplist-value"
  38. "64"
  39. "hll-sparse-max-bytes"
  40. "3000"
  41. "lua-time-limit"
  42. "5000"
  43. "slowlog-log-slower-than"
  44. "10000"
  45. "latency-monitor-threshold"
  46. "0"
  47. "slowlog-max-len"
  48. "128"
  49. "port"
  50. "6379"
  51. "tcp-backlog"
  52. "511"
  53. "databases"
  54. "16"
  55. "repl-ping-slave-period"
  56. "10"
  57. "repl-timeout"
  58. "60"
  59. "repl-backlog-size"
  60. "1048576"
  61. "repl-backlog-ttl"
  62. "3600"
  63. "maxclients"
  64. "4064"
  65. "watchdog-period"
  66. "0"
  67. "slave-priority"
  68. "100"
  69. "min-slaves-to-write"
  70. "0"
  71. "min-slaves-max-lag"
  72. "10"
  73. "hz"
  74. "10"
  75. "no-appendfsync-on-rewrite"
  76. "no"
  77. "slave-serve-stale-data"
  78. "yes"
  79. "slave-read-only"
  80. "yes"
  81. "stop-writes-on-bgsave-error"
  82. "yes"
  83. "daemonize"
  84. "no"
  85. "rdbcompression"
  86. "yes"
  87. "rdbchecksum"
  88. "yes"
  89. "activerehashing"
  90. "yes"
  91. "repl-disable-tcp-nodelay"
  92. "no"
  93. "aof-rewrite-incremental-fsync"
  94. "yes"
  95. "appendonly"
  96. "no"
  97. "dir"
  98. "/home/deepak/Downloads/redis-2.8.13/src"
  99. "maxmemory-policy"
  100. "volatile-lru"
  101. "appendfsync"
  102. "everysec"
  103. "save"
  104. "3600 1 300 100 60 10000"
  105. "loglevel"
  106. "notice"
  107. "client-output-buffer-limit"
  108. "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
  109. "unixsocketperm"
  110. "0"
  111. "slaveof"
  112. ""
  113. "notify-keyspace-events"
  114. ""
  115. "bind"
  116. ""

4.1 编辑配置

你可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。

语法

CONFIG SET 命令基本语法:

redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE

实例

redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
OK
redis 127.0.0.1:6379> CONFIG GET loglevel
  1. "loglevel"
  2. "notice"

4.2 参数说明

redis.conf 配置项说明如下:

1. Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程

    daemonize no

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

    pidfile /var/run/redis.pid

3. 指定 Redis 监听端口,默认端口为 6379,作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口,因为 6379 在手机按键上 MERZ 对应的号码,而 MERZ 取自意大利歌女 Alessia Merz 的名字

    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

5. Redis 持久化概述,RDB 原理、AOF 原理分析

由于 Redis 是基于内存的数据库,为了保证数据的可用性,Redis 提供了两种数据持久化机制:RDB 和 AOF,下面对这两种持久化方式加以分析。

5.1 RDB

运行原理

RDB 模式可以在指定的时间间隔内生成内存中整个数据集的持久化快照。快照文件默认被存储在当前文件夹中,名称为 dump.rdb,可以通过 dir 和 dbfilename 参数来修改默认值。

1.redis调用fork函数复制当前进行的一个副本-子进程
2.父进程继续接收并处理客户端发来的命令
3.子进行将内存中的数据写入一个临时的dump文件
4.子进程写入完成后,会用新的临时dump文件替换就的rdb文件
5.一次持久化完成
  • 1
  • 2
  • 3
  • 4
  • 5

在执行 fork 函数的时候,操作系统会使用写时复制(copy-on-write)策略,也就是说在调用 fork 的一刻,父子进行有相同的内存模型,当父进程要修改其中的某片数据时,操作系统会将该片数据复制一份,从而保证不影响子进程。

rdb 文件是经过压缩的文件,占用的空间比较小,更有利于传输,并且数据恢复速度也比较快。

RDB 模式的优点

1.rdb 持久化文件很紧凑,占用空间更小。 
2.rdb 保存的是基于时间点的数据快照,更适合数据的备份和容灾 
3. 利用 rdb 文件进行数据恢复时,速度更快

RDB 模式的缺点

1. 会造成部分数据的丢失 
2. 当数据集非常大时,fork 操作会占用很多系统资源,造成主服务进程假死

RDB 模式适用的场景

1. 数据备份 
2. 可容忍部分数据丢失 
3. 跨数据中心的容灾备份

5.2 AOF

aof 持久化 记录服务器的所有写操作,并在服务器启动时重新执行这些命令来恢复数据集。aof 文件中的命令全部以 redis 的协议格式存储,新命令会追加到文件的末尾,同时,redis 还会在后台对 aof 文件进行重写,使得 aof 文件的体积不会过大。

aof 机制默认关闭,可以通过appendonly = yes参数开启 aof 机制,通过appendfilename = myaoffile.aof指定 aof 文件名称。

对于触发 aof 重写机制也可以通过配置文件来进行设置:

auto-aof-rewrite-percenttage = 100
auto-aof-rewrite-min-size 64mb
  • 1
  • 2

第一个参数是配置较前一个 aof 文件大小增长的百分比,第二个参数是配置触发 aof 重写的 aof 的最小的大小。

修改 aof 的 fsync 策略:

appendfsync=always   同步持久化每一次修改操作
appendfsync=everysec   每秒想aof文件同步一次
appendfsync=no         关闭向aof文件写入修改
  • 1
  • 2
  • 3

aof 的优点

1. 支持不同的 fsync 策略:no/always/everysec 
2. 能够记录所有写操作,不会造成数据丢失 
3.aof 重写机制确保 aof 文件不会过大 
4.aof 文件可以很容易的读懂

aof 的缺点

1. 虽然有 aof 重写机制,单 aof 文件通常比 rdb 文件大 
2. 在不同的 fsync 策略写,redis 性能会受到一定影响

6. Redis 事务操作分析以及发布订阅模式的操作使用

6.1 Redis 事务

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

6.1.1 实例

以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED

redis 127.0.0.1:6379> GET book-name
QUEUED

redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED

redis 127.0.0.1:6379> SMEMBERS tag
QUEUED

redis 127.0.0.1:6379> EXEC

  1. OK
  2. "Mastering C++ in 21 days"
  3. (integer) 3
    1. "Mastering Series"
    2. "C++"
    3. "Programming" 

6.1.2 事务命令

1    DISCARD 
取消事务,放弃执行事务块内的所有命令。
2    EXEC 
执行所有事务块内的命令。
3    MULTI 
标记一个事务块的开始。
4    UNWATCH 
取消 WATCH 命令对所有 key 的监视。
5    WATCH key [key ...] 
监视一个 (或多个) key ,如果在事务执行之前这个 (或这些) key 被其他命令所改动,那么事务将被打断。

 

6.2 Redis 发布订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

pubsub1

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

pubsub2

6.2.1 实例

以下实例演示了发布订阅是如何工作的。在我们实例中我们创建了订阅频道名为 redisChat:

redis 127.0.0.1:6379> SUBSCRIBE redisChat

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

  1. "subscribe"
  2. "redisChat"
  3. (integer) 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"
  4. "message"
  5. "redisChat"
  6. "Learn redis by runoob.com"

6.2.2 发布订阅命令

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 ...]] 
指退订给定的频道。

7. Redis 集群搭建

Redis 从单机到集群,一步步教你环境部署以及使用

8. Redis 主从复制原理分析

 

9. Redis 的优化建议,最佳实践

1、停止使用 KEYS *

Okay,以挑战这个命令开始这篇文章,或许并不是一个好的方式,但其确实可能是最重要的一点。很多时候当我们关注一个 redis 实例的统计数据,我们会快速地输入”KEYS *”命令,这样 key 的信息会很明显地展示出来。平心而论,从程序化的角度出发往往倾向于写出下面这样的伪代码:

但是当你有 1300 万个 key 时,执行速度将会变慢。因为 KEYS 命令的时间复杂度是 O(n),其中 n 是要返回的 keys 的个数,这样这个命令的复杂度就取决于数据库的大小了。并且在这个操作执行期间,其它任何命令在你的实例中都无法执行。

作为一个替代命令,看一下 SCAN 吧,其允许你以一种更友好的方式来执行… SCAN 通过增量迭代的方式来扫描数据库。这一操作基于游标的迭代器来完成的,因此只要你觉得合适,你可以随时停止或继续。

2、找出拖慢 Redis 的罪魁祸首

由于 Redis 没有非常详细的日志,要想知道在 Redis 实例内部都做了些什么是非常困难的。幸运的是 Redis 提供了一个下面这样的命令统计工具:

通过这个工具可以查看所有命令统计的快照,比如命令执行了多少次,执行命令所耗费的毫秒数 (每个命令的总时间和平均时间)

只需要简单地执行 CONFIG RESETSTAT 命令就可以重置,这样你就可以得到一个全新的统计结果。

3、 将 Redis-Benchmark 结果作为参考,而不要一概而论

Redis 之父 Salvatore 就说过:“通过执行 GET/SET 命令来测试 Redis 就像在雨天检测法拉利的雨刷清洁镜子的效果”。很多时候人们跑到我这里,他们想知道为什么自己的 Redis-Benchmark 统计的结果低于最优结果 。但我们必须要把各种不同的真实情况考虑进来,例如:

  • 可能受到哪些客户端运行环境的限制?
  • 是同一个版本号吗?
  • 测试环境中的表现与应用将要运行的环境是否一致?

Redis-Benchmark 的测试结果提供了一个保证你的 Redis-Server 不会运行在非正常状态下的基准点,但是你永远不要把它作为一个真实的“压力测试”。压力测试需要反应出应用的运行方式,并且需要一个尽可能的和生产相似的环境。

4、Hashes 是你的最佳选择

以一种优雅的方式引入 hashes 吧。hashes 将会带给你一种前所未有的体验。之前我曾看到过许多类似于下面这样的 key 结构:

上面的例子中,foo 可能是一个用户的用户名,其中的每一项都是一个单独的 key。这就增加了 犯错的空间,和一些不必要的 key。使用 hash 代替吧,你会惊奇地发现竟然只需要一个 key :

5、设置 key 值的存活时间

无论什么时候,只要有可能就利用 key 超时的优势。一个很好的例子就是储存一些诸如临时认证 key 之类的东西。当你去查找一个授权 key 时——以 OAUTH 为例——通常会得到一个超时时间。这样在设置 key 的时候,设成同样的超时时间,Redis 就会自动为你清除!而不再需要使用 KEYS * 来遍历所有的 key 了,怎么样很方便吧?

6、 选择合适的回收策略

既然谈到了清除 key 这个话题,那我们就来聊聊回收策略。当 Redis 的实例空间被填满了之后,将会尝试回收一部分 key。根据你的使用方式,我强烈建议使用 volatile-lru 策略——前提是你对 key 已经设置了超时。但如果你运行的是一些类似于 cache 的东西,并且没有对 key 设置超时机制,可以考虑使用 allkeys-lru 回收机制。我的建议是先在这里查看一下可行的方案。

7、如果你的数据很重要,请使用 Try/Except

如果必须确保关键性的数据可以被放入到 Redis 的实例中,我强烈建议将其放入 try/except 块中。几乎所有的 Redis 客户端采用的都是“发送即忘”策略,因此经常需要考虑一个 key 是否真正被放到 Redis 数据库中了。至于将 try/expect 放到 Redis 命令中的复杂性并不是本文要讲的,你只需要知道这样做可以确保重要的数据放到该放的地方就可以了。

8、不要耗尽一个实例

无论什么时候,只要有可能就分散多 redis 实例的工作量。从 3.0.0 版本开始,Redis 就支持集群了。Redis 集群允许你基于 key 范围分离出部分包含主 / 从模式的 key。完整的集群背后的“魔法”可以在这里找到。但如果你是在找教程,那这里是一个再适合不过的地方了。如果不能选择集群,考虑一下命名空间吧,然后将你的 key 分散到多个实例之中。关于怎样分配数据,在 redis.io 网站上有这篇精彩的评论。

9、内核越多越好吗?!

当然是错的。Redis 是一个单线程进程,即使启用了持久化最多也只会消耗两个内核。除非你计划在一台主机上运行多个实例——希望只会是在开发测试的环境下!——否则的话对于一个 Redis 实例是不需要 2 个以上内核的。

10、高可用

到目前为止 Redis Sentinel 已经经过了很全面的测试,很多用户已经将其应用到了生产环境中(包括 ObjectRocket )。如果你的应用重度依赖于 Redis ,那就需要想出一个高可用方案来保证其不会掉线。当然,如果不想自己管理这些东西,ObjectRocket 提供了一个高可用平台,并提供 7×24 小时的技术支持,有意向的话可以考虑一下。

10. Redis 的 JAVA 客户端使用

使用  jedis.jar

链接测试:

package redis;

import redis.clients.jedis.Jedis;

public class RedisJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println(
"连接成功");
//查看服务是否运行
System.out.println("服务正在运行:"+jedis.ping());
jedis.close();
}
}

String:

package redis;

import redis.clients.jedis.Jedis;

public class RedisStringJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println(
"连接成功");
//设置 redis 字符串数据
jedis.set("name", "loveincode");
// 获取存储的数据并输出
System.out.println("redis 存储的字符串为:"+ jedis.get("name"));
jedis.close();
}
}

11. Redis 集成 Spring 的使用

使用 Spring + Jedis 集成 Redis

 

学习笔记部分来自菜鸟教程:http://www.runoob.com/redis/ 、redis 持久化:http://blog.csdn.net/zhangdong2012/article/details/53116213 


文章源自loveincode’s Blog GitHub:loveincode’s Github