《Redis》
简介
Redis(Remote Dictionary Server)是一个开源的内存数据库,遵守 BSD 协议,它提供了一个高性能的键值(key-value)存储系统,常用于缓存、消息队列、会话存储等应用场景。
- 性能极高 :Redis 以其极高的性能而著称,能够支持每秒数十万次的读写操作24。这使得Redis成为处理高并发请求的理想选择,尤其是在需要快速响应的场景中,如缓存、会话管理、排行榜等。
- 丰富的数据类型:Redis 不仅支持基本的键值存储,还提供了丰富的数据类型,包括字符串、列表、集合、哈希表、有序集合等。这些数据类型为开发者提供了灵活的数据操作能力,使得Redis可以适应各种不同的应用场景。
- 原子性操作:Redis 的所有操作都是原子性的,这意味着操作要么完全执行,要么完全不执行。这种特性对于确保数据的一致性和完整性至关重要,尤其是在高并发环境下处理事务时。
- 持久化:Redis 支持数据的持久化,可以将内存中的数据保存到磁盘中,以便在系统重启后恢复数据。这为 Redis 提供了数据安全性,确保数据不会因为系统故障而丢失。
- 支持发布/订阅模式:Redis 内置了发布/订阅模式(Pub/Sub),允许客户端之间通过消息传递进行通信。这使得 Redis 可以作为消息队列和实时数据传输的平台。
- 单线程模型:尽管 Redis 是单线程的,但它通过高效的事件驱动模型来处理并发请求,确保了高性能和低延迟。单线程模型也简化了并发控制的复杂性。
- 主从复制:Redis 支持主从复制,可以通过从节点来备份数据或分担读请求,提高数据的可用性和系统的伸缩性。
- 应用场景广泛:Redis 被广泛应用于各种场景,包括但不限于缓存系统、会话存储、排行榜、实时分析、地理空间数据索引等。
- 社区支持:Redis 拥有一个活跃的开发者社区,提供了大量的文档、教程和第三方库,这为开发者提供了强大的支持和丰富的资源。
- 跨平台兼容性:Redis 可以在多种操作系统上运行,包括 Linux、macOS 和 Windows,这使得它能够在不同的技术栈中灵活部署。
与其他key-value存储的不同
Redis 与其他 key-value 存储系统的主要区别在于其提供了丰富的数据类型、高性能的读写能力、原子性操作、持久化机制、以及丰富的特性集。
以下是 Redis 的一些独特之处:
- 丰富的数据类型:Redis 不仅仅支持简单的 key-value 类型的数据,还提供了 list、set、zset(有序集合)、hash 等数据结构的存储。这些数据类型可以更好地满足特定的业务需求,使得 Redis 可以用于更广泛的应用场景。
- 高性能的读写能力:Redis 能读的速度是 110000次/s,写的速度是 81000次/s。这种高性能主要得益于 Redis 将数据存储在内存中,从而显著提高了数据的访问速度。
- 原子性操作:Redis 的所有操作都是原子性的,这意味着操作要么完全执行,要么完全不执行。这种特性对于确保数据的一致性和完整性非常重要。
- 持久化机制:Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,以便在系统重启后能够再次加载使用。这为 Redis 提供了数据安全性,确保数据不会因为系统故障而丢失。
- 丰富的特性集:Redis 还支持 publish/subscribe(发布/订阅)模式、通知、key 过期等高级特性。这些特性使得 Redis 可以用于消息队列、实时数据分析等复杂的应用场景。
- 主从复制和高可用性:Redis 支持 master-slave 模式的数据备份,提供了数据的备份和主从复制功能,增强了数据的可用性和容错性。
- 支持 Lua 脚本:Redis 支持使用 Lua 脚本来编写复杂的操作,这些脚本可以在服务器端执行,提供了更多的灵活性和强大的功能。
- 单线程模型:尽管 Redis 是单线程的,但它通过高效的事件驱动模型来处理并发请求,确保了高性能和低延迟。
Redis 数据类型
Redis 主要支持以下几种数据类型:
- string(字符串): 基本的数据存储单元,可以存储字符串、整数或者浮点数。
- hash(哈希):一个键值对集合,可以存储多个字段。
- list(列表):一个简单的列表,可以存储一系列的字符串元素。
- set(集合):一个无序集合,可以存储不重复的字符串元素。
- zset(sorted set:有序集合): 类似于集合,但是每个元素都有一个分数(score)与之关联。
- 位图(Bitmaps):基于字符串类型,可以对每个位进行操作。
- 超日志(HyperLogLogs):用于基数统计,可以估算集合中的唯一元素数量。
- 地理空间(Geospatial):用于存储地理位置信息。
- 发布/订阅(Pub/Sub):一种消息通信模式,允许客户端订阅消息通道,并接收发布到该通道的消息。
- 流(Streams):用于消息队列和日志存储,支持消息的持久化和时间排序。
- 模块(Modules):Redis 支持动态加载模块,可以扩展 Redis 的功能。
String(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据,比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
常用命令
SET key value
:设置键的值。GET key
:获取键的值。INCR key
:将键的值加 1。DECR key
:将键的值减 1。APPEND key value
:将值追加到键的值之后。
注意:一个键最大能存储 512MB。
Hash(哈希)
Redis hash 是一个键值(key=>value)对集合,类似于一个小型的 NoSQL 数据库。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
每个哈希最多可以存储 2^32 - 1 个键值对。
常用命令
HSET key field value
:设置哈希表中字段的值。HGET key field
:获取哈希表中字段的值。HGETALL key
:获取哈希表中所有字段和值。HDEL key field
:删除哈希表中的一个或多个字段。
List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
列表最多可以存储 2^32 - 1 个元素。
常用命令
LPUSH key value
:将值插入到列表头部。RPUSH key value
:将值插入到列表尾部。LPOP key
:移出并获取列表的第一个元素。RPOP key
:移出并获取列表的最后一个元素。LRANGE key start stop
:获取列表在指定范围内的元素。
Set(集合)
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
常用命令
SADD key value
:向集合添加一个或多个成员。SREM key value
:移除集合中的一个或多个成员。SMEMBERS key
:返回集合中的所有成员。SISMEMBER key value
:判断值是否是集合的成员。
sadd 命令
添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
sadd key member |
注意:根据集合内元素的唯一性,第二次插入的元素将被忽略。
zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
常用命令
ZADD key score value
:向有序集合添加一个或多个成员,或更新已存在成员的分数。ZRANGE key start stop [WITHSCORES]
:返回指定范围内的成员。ZREM key value
:移除有序集合中的一个或多个成员。ZSCORE key value
:返回有序集合中,成员的分数值。
zdd 命令
添加元素到集合,元素在集合中存在则更新对应score
zadd key score member |
其他高级数据类型
HyperLogLog
- 用于基数估计算法的数据结构。
- 常用于统计唯一值的近似值。
Bitmaps
- 位数组,可以对字符串进行位操作。
- 常用于实现布隆过滤器等位操作。
Geospatial Indexes
-
处理地理空间数据,支持地理空间索引和半径查询。
-
Streams
-
日志数据类型,支持时间序列数据。
用于消息队列和实时数据处理。
-
Redis 命令
Redis 命令用于在 redis 服务上执行操作。
要在 redis 服务上执行命令需要一个 redis 客户端。Redis 客户端在我们之前下载的的 redis 的安装包中。
本地服务命令
Redis 客户端的基本语法为:
$ redis-cli |
$ redis-cli |
在以上实例中我们连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动。
在远处服务上执行命令
如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。
$ redis-cli -h host -p port -a password |
Redis 键(key)
KEYS
命令在生产环境慎用,因为它会全量扫描所有 key,可能造成阻塞;- 推荐使用
SCAN
进行非阻塞式遍历; TTL
和PTTL
用于查看过期倒计时,非常适合做缓存策略调试;TYPE
是调试利器,适合在不确定 value 类型时使用。
序号 | 命令 | 描述 |
---|---|---|
1 | DEL key |
删除指定的 key(如果存在)。 |
2 | DUMP key |
序列化指定 key 并返回序列化值。 |
3 | EXISTS key |
检查指定 key 是否存在,存在返回 1。 |
4 | EXPIRE key seconds |
设置 key 的过期时间(单位:秒)。 |
5 | EXPIREAT key timestamp |
设置 key 在指定时间点过期(UNIX 时间戳,单位秒)。 |
6 | PEXPIRE key milliseconds |
设置 key 的过期时间(单位:毫秒)。 |
7 | PEXPIREAT key milliseconds-timestamp |
设置 key 在指定时间点过期(UNIX 时间戳,单位毫秒)。 |
8 | KEYS pattern |
查找匹配指定模式的所有 key(慎用,性能差)。 |
9 | MOVE key db |
将 key 从当前数据库移动到指定数据库(db 编号)。 |
10 | PERSIST key |
移除 key 的过期时间,使其永久存在。 |
11 | PTTL key |
获取 key 的剩余过期时间(毫秒)。 |
12 | TTL key |
获取 key 的剩余过期时间(秒)。 |
13 | RANDOMKEY |
随机返回当前数据库中的一个 key。 |
14 | RENAME key newkey |
将 key 重命名为 newkey(覆盖原值)。 |
15 | RENAMENX key newkey |
如果 newkey 不存在,则将 key 重命名为 newkey。 |
16 | SCAN cursor [MATCH pattern] [COUNT count] |
增量迭代遍历数据库中的 key(用于大数据量 key 查询)。 |
17 | TYPE key |
返回 key 储存值的数据类型(如 string、list、set 等)。 |
Redis 字符串(String)
Redis 字符串数据类型的相关命令用于管理 redis 字符串值
序号 | 命令 | 描述 |
---|---|---|
1 | SET key value |
设置指定 key 的值。 |
2 | GET key |
获取指定 key 的值。 |
3 | GETRANGE key start end |
返回 key 中字符串值的子字符。 |
4 | GETSET 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 |
设置 key 的值及过期时间(秒)。 |
9 | SETNX key value |
仅在 key 不存在时设置值。 |
10 | SETRANGE key offset value |
从 offset 开始覆盖 key 的值。 |
11 | STRLEN key |
返回 key 所储存字符串的长度。 |
12 | MSET key value [key value ...] |
批量设置多个 key-value 对。 |
13 | MSETNX key value [key value ...] |
所有 key 不存在时批量设置。 |
14 | PSETEX key milliseconds value |
毫秒精度设置过期时间并赋值。 |
15 | INCR key |
key 对应值自增 1。 |
16 | INCRBY key increment |
key 对应值增加指定整数。 |
17 | INCRBYFLOAT key increment |
key 对应值增加指定浮点数。 |
18 | DECR key |
key 对应值自减 1。 |
19 | DECRBY key decrement |
key 对应值减少指定整数。 |
20 | APPEND key value |
向已有字符串值末尾追加内容。 |
Redis 哈希(Hash)
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
序号 | 命令 | 描述 |
---|---|---|
1 | HDEL key field1 [field2] |
删除哈希表中一个或多个字段。 |
2 | HEXISTS key field |
检查指定字段是否存在于哈希表中。 |
3 | HGET key field |
获取哈希表中指定字段的值。 |
4 | HGETALL key |
获取哈希表中所有字段和值(以 field-value 对返回)。 |
5 | HINCRBY key field increment |
将哈希表中指定字段的整数值加上指定增量。 |
6 | HINCRBYFLOAT key field increment |
将哈希表中指定字段的浮点值加上指定增量。 |
7 | HKEYS key |
返回哈希表中的所有字段。 |
8 | HLEN key |
返回哈希表中字段的数量。 |
9 | HMGET key field1 [field2] |
获取多个字段对应的值。 |
10 | HMSET key field1 value1 [field2 value2] |
同时设置多个字段的值(已被 HSET 替代)。 |
11 | HSET key field value |
设置哈希表字段的值(若字段存在则覆盖)。 |
12 | HSETNX key field value |
仅当字段不存在时设置字段值。 |
13 | HVALS key |
返回哈希表中所有字段的值。 |
14 | HSCAN key cursor [MATCH pattern] [COUNT count] |
增量迭代哈希表中的字段和值对。 |
- Redis Hash 结构常用于存储对象(如:用户信息、商品信息),字段对应属性名;
HGETALL
、HKEYS
和HVALS
都是一次性全量操作,不建议用于超大哈希;HSCAN
更适合大数据量场景,支持游标式遍历;HSETNX
是原子操作,用于保障初始化字段不被覆盖。
Redis 列表(List)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
序号 | 命令 | 描述 |
---|---|---|
1 | BLPOP key1 [key2] timeout |
弹出并获取列表的第一个元素,如果没有元素则阻塞等待,直到超时或有元素可弹出。 |
2 | BRPOP key1 [key2] timeout |
弹出并获取列表的最后一个元素,行为与 BLPOP 类似。 |
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 |
删除指定值的元素,count 控制删除个数和方向。 |
12 | LSET key index value |
通过索引设置列表中元素的新值。 |
13 | LTRIM key start stop |
保留列表中指定范围的元素,其余的将被移除。 |
14 | RPOP key |
弹出列表的最后一个元素。 |
15 | RPOPLPUSH source destination |
从源列表右弹出元素并推入目标列表左侧。 |
16 | RPUSH key value1 [value2...] |
在列表尾部插入一个或多个值。 |
17 | RPUSHX key value |
仅当列表存在时,才在尾部添加元素。 |
- Redis 列表是双向链表结构,支持高效头尾插入与弹出操作;
- 阻塞命令(如
BLPOP
、BRPOP
)适合生产者-消费者模型; LREM
的参数count
可控制从头/尾方向、删除个数:count > 0
:从头开始删除;count < 0
:从尾开始删除;count = 0
:删除所有匹配值;
LTRIM
可用于列表裁剪,配合LRANGE
实现分页
Redis 集合(Set)
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
集合对象的编码可以是 intset 或者 hashtable。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
序号 | 命令 | 描述 |
---|---|---|
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] |
迭代集合中的元素(用于大集合分页遍历) |
Redis 有序集合(sorted set)
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
序号 | 命令 | 描述 |
---|---|---|
1 | ZADD key score1 member1 [score2 member2] |
向有序集合添加一个或多个成员,或更新已存在成员的分数 |
2 | ZCARD key |
获取有序集合的成员数 |
3 | ZCOUNT key min max |
统计分数在指定区间内的成员数量 |
4 | ZINCRBY key increment member |
增加指定成员的分数值 |
5 | ZINTERSTORE destination numkeys 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 offset count] |
按分数区间升序返回成员,可选带分数和分页 |
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 HyperLogLog
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
序号 | 命令 | 描述 |
---|---|---|
1 | PFADD key element [element ...] |
向 HyperLogLog 添加指定元素 |
2 | PFCOUNT key [key ...] |
返回给定 HyperLogLog 的基数估算值 |
3 | PFMERGE destkey sourcekey [sourcekey ...] |
合并多个 HyperLogLog,并存储到目标 key 中 |
Redis 发布订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
序号 | 命令 | 描述 |
---|---|---|
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 ...]] |
退订一个或多个指定的频道 |
Redis 事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
比如:
redis 127.0.0.1:7000> multi |
如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。
序号 | 命令 | 描述 |
---|---|---|
1 | DISCARD |
取消事务,放弃执行事务块内的所有命令 |
2 | EXEC |
执行所有事务块内的命令 |
3 | MULTI |
标记一个事务块的开始 |
4 | UNWATCH |
取消 WATCH 命令对所有 key 的监视 |
5 | WATCH key [key ...] |
监视一个或多个 key,如果在事务执行前被其他命令修改,事务将被打断 |
Redis 脚本
Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。
序号 | 命令 | 描述 |
---|---|---|
1 | EVAL script numkeys key [key ...] arg [arg ...] |
执行 Lua 脚本 |
2 | EVALSHA sha1 numkeys key [key ...] arg [arg ...] |
根据 SHA1 执行已缓存的 Lua 脚本 |
3 | SCRIPT EXISTS script [script ...] |
查看指定的脚本是否已被保存在缓存中 |
4 | SCRIPT FLUSH |
从脚本缓存中移除所有脚本 |
5 | SCRIPT KILL |
杀死当前正在运行的 Lua 脚本 |
6 | SCRIPT LOAD script |
将脚本添加到脚本缓存中,但不立即执行 |
Redis 连接
Redis 连接命令主要是用于连接 redis 服务。
序号 | 命令 | 描述 |
---|---|---|
1 | AUTH password |
验证密码是否正确,用于身份验证。 |
2 | ECHO message |
打印指定字符串,常用于测试连接。 |
3 | PING |
测试连接是否仍然活跃,返回 PONG 。 |
4 | QUIT |
关闭当前连接。 |
5 | SELECT index |
切换到指定编号的数据库(0~15)。 |
Redis 服务器
Redis 服务器命令主要是用于管理 redis 服务。
序号 | 命令 | 描述 |
---|---|---|
1 | BGREWRITEAOF |
异步执行 AOF 文件重写操作,减少文件体积。 |
2 | BGSAVE |
在后台异步保存当前数据库数据到磁盘。 |
3 | CLIENT KILL [ip:port] [ID client-id] |
关闭指定客户端连接。 |
4 | CLIENT LIST |
获取所有连接客户端的列表。 |
5 | CLIENT GETNAME |
获取当前连接的名称。 |
6 | CLIENT PAUSE timeout |
暂停客户端命令执行,指定时间内阻止命令处理。 |
7 | CLIENT SETNAME connection-name |
设置当前连接的名称。 |
8 | CLUSTER SLOTS |
获取集群节点槽位映射信息(集群模式下)。 |
9 | COMMAND |
获取所有 Redis 命令的详情信息。 |
10 | COMMAND COUNT |
获取 Redis 命令总数。 |
11 | COMMAND GETKEYS |
获取指定命令中涉及的所有 key。 |
12 | TIME |
返回服务器当前时间。 |
13 | COMMAND INFO command-name [command-name ...] |
获取指定命令的详细描述信息。 |
14 | CONFIG GET parameter |
获取配置参数的当前值。 |
15 | CONFIG REWRITE |
重新写入启动时使用的配置文件 redis.conf。 |
16 | CONFIG SET parameter value |
修改 Redis 配置参数,实时生效,无需重启。 |
17 | CONFIG RESETSTAT |
重置统计信息(INFO 命令显示的统计数据)。 |
18 | DBSIZE |
返回当前数据库中 key 的数量。 |
19 | DEBUG OBJECT key |
获取 key 的调试信息。 |
20 | DEBUG SEGFAULT |
使 Redis 服务器崩溃(用于调试)。 |
21 | FLUSHALL |
删除所有数据库中的所有 key。 |
22 | FLUSHDB |
删除当前数据库的所有 key。 |
23 | INFO [section] |
获取服务器各类信息和统计数据。 |
24 | LASTSAVE |
返回最近一次成功保存数据到磁盘的 UNIX 时间戳。 |
25 | MONITOR |
实时打印接收到的所有命令,调试时使用。 |
26 | ROLE |
返回当前实例的角色信息(主/从/哨兵)。 |
27 | SAVE |
同步保存当前数据库数据到硬盘。 |
28 | SHUTDOWN [NOSAVE] [SAVE] |
异步保存数据并关闭服务器。 |
29 | SLAVEOF host port |
将当前服务器设置为指定主服务器的从服务器。 |
30 | SLOWLOG subcommand [argument] |
管理慢查询日志。 |
31 | SYNC |
复制功能的内部命令,用于主从同步。 |
Redis GEO
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
- geoadd:添加地理位置的坐标。
- geopos:获取地理位置的坐标。
- geodist:计算两个位置之间的距离。
- georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
- georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
- geohash:返回一个或多个位置对象的 geohash 值。
geoadd
geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
geoadd 语法格式如下:
GEOADD key longitude latitude member [longitude latitude member ...] |
geopos
geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
geopos 语法格式如下:
GEOPOS key member [member ...] |
geodist
geodist 用于返回两个给定位置之间的距离。
geodist 语法格式如下:
GEODIST key member1 member2 [m|km|ft|mi] |
member1 member2 为两个地理位置。
最后一个距离单位参数说明:
- m :米,默认单位。
- km :千米。
- mi :英里。
- ft :英尺。
georadius、georadiusbymember
-
georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
-
georadiusbymember 和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
-
georadius 与 georadiusbymember 语法格式如下:
-
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
-
参数说明:
-
m :米,默认单位。
km :千米。
mi :英里。
ft :英尺。
WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
WITHCOORD: 将位置元素的经度和纬度也一并返回。
WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
COUNT 限定返回的记录数。
ASC: 查找结果根据距离从近到远排序。
DESC: 查找结果根据从远到近排序。
geohash
- Redis GEO 使用 geohash 来保存地理位置的坐标。
- geohash 用于获取一个或多个位置元素的 geohash 值。
- geohash 语法格式如下:
- GEOHASH key member [member …]
Redis Stream
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。
上图解析:
- Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
- last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
- pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。
消息队列相关命令:
- XADD - 添加消息到末尾
- XTRIM - 对流进行修剪,限制长度
- XDEL - 删除消息
- XLEN - 获取流包含的元素数量,即消息长度
- XRANGE - 获取消息列表,会自动过滤已经删除的消息
- XREVRANGE - 反向获取消息列表,ID 从大到小
- XREAD - 以阻塞或非阻塞方式获取消息列表
消费者组相关命令:
- XGROUP CREATE - 创建消费者组
- XREADGROUP GROUP - 读取消费者组中的消息
- XACK - 将消息标记为"已处理"
- XGROUP SETID - 为消费者组设置新的最后递送消息ID
- XGROUP DELCONSUMER - 删除消费者
- XGROUP DESTROY - 删除消费者组
- XPENDING - 显示待处理消息的相关信息
- XCLAIM - 转移消息的归属权
- XINFO - 查看流和消费者组的相关信息;
- XINFO GROUPS - 打印消费者组的信息;
- XINFO STREAM - 打印流信息
XADD
使用 XADD 向队列添加消息,如果指定的队列不存在,则创建一个队列,XADD 语法格式:
XADD key ID field value [field value ...] |
- key :队列名称,如果不存在就创建
- ID :消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性。
- field value : 记录。
XTRIM
使用 XTRIM 对流进行修剪,限制长度, 语法格式:
XTRIM key MAXLEN [~] count |
- key :队列名称
- MAXLEN :长度
- count :数量
XDEL
使用 XDEL 删除消息,语法格式:
XDEL key ID [ID ...] |
- key:队列名称
- ID :消息 ID
XLEN
使用 XLEN 获取流包含的元素数量,即消息长度,语法格式:
XLEN key |
- key:队列名称
XRANGE
使用 XRANGE 获取消息列表,会自动过滤已经删除的消息 ,语法格式:
XRANGE key start end [COUNT count] |
- key :队列名
- start :开始值, - 表示最小值
- end :结束值, + 表示最大值
- count :数量
XREVRANGE
使用 XREVRANGE 获取消息列表,会自动过滤已经删除的消息 ,语法格式:
XREVRANGE key end start [COUNT count] |
- key :队列名
- end :结束值, + 表示最大值
- start :开始值, - 表示最小值
- count :数量
XREAD
使用 XREAD 以阻塞或非阻塞方式获取消息列表 ,语法格式:
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...] |
- count :数量
- milliseconds :可选,阻塞毫秒数,没有设置就是非阻塞模式
- key :队列名
- id :消息 ID
XGROUP CREATE
使用 XGROUP CREATE 创建消费者组,语法格式:
XGROUP [CREATE key groupname id-or-$] [SETID key groupname id-or-$] [DESTROY key groupname] [DELCONSUMER key groupname consumername] |
- key :队列名称,如果不存在就创建
- groupname :组名。
- $ : 表示从尾部开始消费,只接受新消息,当前 Stream 消息会全部忽略。
从头开始消费:
XGROUP CREATE mystream consumer-group-name 0-0 |
从尾部开始消费:
XGROUP CREATE mystream consumer-group-name $ |
XREADGROUP GROUP
使用 XREADGROUP GROUP 读取消费组中的消息,语法格式:
XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...] |
- group :消费组名
- consumer :消费者名。
- count : 读取数量。
- milliseconds : 阻塞毫秒数。
- key : 队列名。
- ID : 消息 ID。
XREADGROUP GROUP consumer-group-name consumer-name COUNT 1 STREAMS mystream > |
Redis 数据备份与恢复
Redis SAVE 命令用于创建当前数据库的备份。
基本语法如下:
redis 127.0.0.1:6379> SAVE |
恢复数据
如果需要恢复数据,只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。获取 redis 目录可以使用 CONFIG 命令,如下所示:
redis 127.0.0.1:6379> CONFIG GET dir |
以上命令 CONFIG GET dir 输出的 redis 安装目录为 /usr/local/redis/bin。
Bgsave
创建 redis 备份文件也可以使用命令 BGSAVE,该命令在后台执行
Redis 安全
我们可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全。
我们可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG get requirepass |
默认情况下 requirepass 参数是空的,这就意味着你无需通过密码验证就可以连接到 redis 服务。
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "runoob" |
设置密码后,客户端连接 redis 服务就需要密码验证,否则无法执行命令。
AUTH 命令基本语法格式如下:
127.0.0.1:6379> AUTH password |
Redis 性能测试
Redis 性能测试是通过同时执行多个命令实现的。
基本命令如下:
redis-benchmark [option] [option value] |
注意:该命令是在 redis 的目录下执行的,而不是 redis 客户端的内部指令。
以下实例同时执行 10000 个请求来检测性能:
$ redis-benchmark -n 10000 -q |
redis 性能测试工具可选参数如下所示:
序号 | 选项 | 描述 | 默认值 |
---|---|---|---|
1 | -h |
指定服务器主机名 | 127.0.0.1 |
2 | -p |
指定服务器端口 | 6379 |
3 | -s |
指定服务器 socket 文件路径 | 无 |
4 | -c |
指定并发连接数 | 50 |
5 | -n |
指定请求数 | 10000 |
6 | -d |
以字节为单位指定 SET/GET 值的数据大小 | 2 |
7 | -k |
1 = 长连接(keep alive),0 = 每次请求重连 | 1 |
8 | -r |
使用随机 key(SET/GET/INCR),SADD 使用随机值 | 无 |
9 | -P |
使用管道传输 请求 | 1 |
10 | -q |
强制退出,仅显示每秒查询数(QPS) | 无 |
11 | --csv |
以 CSV 格式输出结果 | 无 |
12 | -l (小写L) |
循环执行测试,持续运行 | 无 |
13 | -t |
仅运行指定的以逗号分隔的测试命令列表 | 无 |
14 | -I (大写i) |
Idle 模式,仅打开指定数量空闲连接并等待 | 无 |
以下实例我们使用了多个参数来测试 redis 性能:
$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q |
以上实例中主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,通过 -q 参数让结果只显示每秒执行的请求数。
Redis 客户端连接
Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作:
- 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。
- 然后为这个 socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法
- 然后创建一个可读的文件事件用于监听这个客户端 socket 的数据发送
最大连接数
在 Redis2.4 中,最大连接数是被直接硬编码在代码里面的,而在2.6版本中这个值变成可配置的。
maxclients 的默认值是 10000,你也可以在 redis.conf 中对这个值进行修改。
config get maxclients |
序号 | 命令 | 描述 |
---|---|---|
1 | CLIENT LIST | 返回连接到 Redis 服务的客户端列表 |
2 | CLIENT SETNAME | 设置当前连接的名称 |
3 | CLIENT GETNAME | 获取通过 CLIENT SETNAME 设置的连接名称 |
4 | CLIENT PAUSE | 挂起客户端连接,指定挂起时间(毫秒) |
5 | CLIENT KILL | 关闭客户端连接 |
Redis 管道技术
Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
- 服务端处理命令,并将结果返回给客户端。
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
查看 redis 管道,只需要启动 redis 实例并输入以下命令:
$(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379 |
以上实例中我们通过使用 PING 命令查看redis服务是否可用, 之后我们设置了 runoobkey 的值为 redis,然后我们获取 runoobkey 的值并使得 visitor 自增 3 次。
在返回的结果中我们可以看到这些命令一次性向 redis 服务提交,并最终一次性读取所有服务端的响应
管道技术的优势
管道技术最显著的优势是提高了 redis 服务的性能。
在下面的测试中,我们将使用Redis的Ruby客户端,支持管道技术特性,测试管道技术对速度的提升效果。
require 'rubygems' |
从处于局域网中的Mac OS X系统上执行上面这个简单脚本的数据表明,开启了管道操作后,往返延时已经被改善得相当低了。
without pipelining 1.185238 seconds |
如你所见,开启管道后,我们的速度效率提升了5倍。
Redis 分区
分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。
分区的优势
- 通过利用多台计算机内存的和值,允许我们构造更大的数据库。
- 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。
分区的不足
redis的一些特性在分区方面表现的不是很好:
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
- 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。
分区类型
Redis 有两种类型分区。 假设有4个Redis实例 R0,R1,R2,R3,和类似user:1,user:2这样的表示用户的多个key,对既定的key有多种不同方式来选择这个key存放在哪个实例中。也就是说,有不同的系统来映射某个key到某个Redis服务。
范围分区
最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例。
比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推。
这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各 种对象的映射表,通常对Redis来说并非是好的方法。
哈希分区
另外一种分区方法是hash分区。这对任何key都适用,也无需是object_name:这种形式,像下面描述的一样简单:
- 用一个hash函数将key转换为一个数字,比如使用crc32 hash函数。对key foobar执行crc32(foobar)会输出类似93024922的整数。
- 对这个整数取模,将其转化为0-3之间的数字,就可以将这个整数映射到4个Redis实例中的一个了。93024922 % 4 = 2,就是说key foobar应该被存到R2实例中。注意:取模操作是取除的余数,通常在多种编程语言中用%操作符实现。