Redis,全名Remote Dictionary Server,是一种开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等,并且提供丰富的命令来操作这些数据结构。此外,Redis还提供了发布/订阅(publish/subscribe)模式的的消息队列功能。
1.0 Redis的特点
-
高性能:Redis是完全在内存中运行的,数据读写速度非常快,每秒可以执行数十万次读写操作,是传统关系型数据库的数倍。
-
数据持久化:虽然Redis主要驻留在内存中,但它也提供了一些策略来将数据持久化到磁盘上,以防服务器突然断电导致数据丢失。主要有两种方式,一种是RDB(快照),另一种是AOF(日志)。
-
支持主从复制:Redis支持多个副本,可以进行数据备份和负载均衡,提高系统的可用性。
-
多种数据类型:Redis支持丰富的数据类型,包括字符串、哈希、列表、集合、有序集合等,这使得它可以用于各种场景。
-
事务处理:Redis支持简单的事务操作,可以在一次命令执行中完成多个操作,保证了操作的原子性。
-
发布/订阅:Redis内置了发布/订阅功能,可以作为消息队列使用,实现进程间通信。
-
范围查询:对于有序集合,Redis支持范围查询,这对于某些需要排序或者分页的应用非常有用。
2.0 Redis的使用场景
-
缓存:由于Redis的操作速度快,常被用作Web应用的缓存系统,减轻数据库的压力。
-
计数器:例如网站的访问量统计,用户的点赞、收藏等操作计数。
-
排行榜:利用有序集合的特性,可以方便地实现动态更新的排行榜。
-
消息队列:通过Redis的发布/订阅功能,可以构建消息队列系统,实现异步处理任务。
-
分布式锁:在分布式系统中,Redis可以用来实现分布式锁。
-
社交网络:例如好友推荐、用户关注列表等。
3.0 Redis的安装与配置
Redis通常以服务的形式运行在Linux或Windows服务器上,可以通过下载源码编译安装,也可以直接使用预编译的二进制包。安装后,通过修改配置文件redis.conf,可以设置端口、最大客户端连接数、内存大小限制、持久化策略等参数。
4.0 Redis的未来
随着云计算和大数据的发展,Redis也在不断进化。例如,Redis Cluster提供了一种无中心节点的分布式解决方案,可以自动处理数据分区和故障恢复。另外,Redis 6引入了多线程模型,进一步提高了性能。同时,社区也在开发更多的插件和扩展,如RediSearch(全文搜索)和RedisGears(脚本处理)等,使得Redis能更好地服务于各种复杂的业务需求。
总结,Redis以其高性能、易用性和灵活性,成为了现代互联网应用的重要基础设施之一。无论是在传统的web应用,还是在新兴的大数据、物联网等领域,我们都能看到Redis的身影。
5.0 Redis十种数据类型
5.1.0 String(字符串)
Redis 字符串存储字节序列,包括文本、序列化对象和二进制数组。 因此字符串是可以关联的最简单的值类型 一个 Redis 密钥。 它们通常用于缓存,但它们支持其他功能,使你能够实现计数器并执行按位操作。
由于 Redis 键是字符串,因此当我们也使用字符串类型作为值时, 我们正在将一个字符串映射到另一个字符串。字符串数据类型很有用 适用于许多用例,例如缓存 HTML 片段或页面。
> SET bike:1 Deimos
OK
> GET bike:1
"Deimos"
正如你所看到的,使用 SET 和 GET 命令是我们设置的方式 并检索字符串值。请注意,SET 将替换任何现有值 已存储到密钥中,如果密钥已存在,即使 该键与非字符串值相关联。因此 SET 执行任务。
值可以是各种类型的字符串(包括二进制数据),例如 可以将 JPEG 图像存储在值中。值不能大于 512 MB。
SET 命令具有有趣的选项,这些选项作为附加选项提供参数。例如,如果密钥已经存在,我可能会要求 SET 失败, 或者相反,只有当密钥已经存在时,它才会成功:
> set bike:1 bike nx
(nil)
> set bike:1 bike xx
OK
还有许多其他命令可用于对字符串进行操作。例如 GETSET 命令将键设置为新值,并将旧值作为 结果。您可以使用此命令,例如,如果您有一个 每次网站收到新访问者时,使用 INCR 递增 Redis 密钥的系统。你可能想收集这个 每小时提供一次信息,不会丢失任何增量。 您可以 GETSET 键,为其分配新值“0”并读取 旧值回来了。
能够在单个键中设置或检索多个键的值 命令对于减少延迟也很有用。出于这个原因,有 MSET和 MGET 命令:
> mset bike:1 "Deimos" bike:2 "Ares" bike:3 "Vanth"
OK
> mget bike:1 bike:2 bike:3
1) "Deimos"
2) "Ares"
3) "Vanth"
5.1.1 字符串作为计数器
> set total_crashes 0
OK
> incr total_crashes
(integer) 1
> incrby total_crashes 10
(integer) 11
INCR 命令将字符串值解析为整数, 将其递增 1,最后将获得的值设置为新值。 还有其他类似的命令,如 INCRBY、DECR 和 DECRBY 在内部,它是 始终相同的命令,以略有不同的方式行事。
INCR是原子性的是什么意思? 多个客户发出 INCR 反对同一密钥永远不会进入争用条件。例如,它永远不会碰巧客户端 1 同时读取“10”,客户端 2 同时读取“10”,两者 递增到 11,并将新值设置为 11。最终值将始终为 12 和 read-increment-set 操作执行,而所有其他 客户端未同时执行命令。
5.2.0 Hash(哈希)
Redis 哈希是结构为字段值对集合的记录类型。 可以使用哈希来表示基本对象并存储计数器分组等。
> HSET bike:1 model Deimos brand Ergonom type 'Enduro bikes' price 4972
(integer) 4
> HGET bike:1 model
"Deimos"
> HGET bike:1 price
"4972"
> HGETALL bike:1
1) "model"
2) "Deimos"
3) "brand"
4) "Ergonom"
5) "type"
6) "Enduro bikes"
7) "price"
8) "4972"
虽然哈希值对于表示对象很方便,但实际上可以表示字段的数量 放入哈希没有实际限制(可用内存除外),因此可以使用 在应用程序中以多种不同的方式进行哈希处理。
HSET 设置哈希的多个字段,而 HGET 检索 单个字段。HMGET 类似于 HGET,但返回值数组:
> HMGET bike:1 model price no-such-field
1) "Deimos"
2) "4972"
3) (nil)
有些命令能够对单个字段执行操作 以及,如 HINCRBY:
> HINCRBY bike:1 price 100
(integer) 5072
> HINCRBY bike:1 price -100
(integer) 4972
5.3.0 List(列表)
List类型是一种有序的字符串列表,可以存储多个字符串,支持的操作包括从列表左侧或右侧插入和删除元素、获取列表长度等。
Redis 列表是字符串值的链表。 Redis 列表经常用于:
- 实现堆栈和队列。
- 为后台工作器系统构建队列管理。
List基本命令:
- LPUSH 将新元素添加到列表的头部;RPUSH添加到尾巴上。
- LPOP 从列表的头部删除并返回一个元素;RPOP执行相同的操作,但从列表的尾部开始。
- LLEN 返回列表的长度。
- LMOVE以原子方式将元素从一个列表移动到另一个列表。
- LTRIM 将列表缩小到指定的元素范围。
阻止命令:
列表支持多个阻塞命令。 例如:
- BLPOP 从列表的头部删除并返回一个元素。 如果列表为空,则命令将阻塞,直到元素变为可用或达到指定的超时。
- BLMOVE 以原子方式将元素从源列表移动到目标列表。 如果源列表为空,则该命令将阻塞,直到新元素可用。
5.4.0 Set(集合)
Redis 集是唯一字符串(成员)的无序集合。 您可以使用 Redis 集有效地执行以下操作:
- 跟踪唯一项目(例如,跟踪访问给定博客文章的所有唯一 IP 地址)。
- 表示关系(例如,具有给定角色的所有用户的集合)。
- 执行常见的集合运算,例如交集、并集和差分
基本命令:
- SADD 将新成员添加到集合中。
- SREM 从集合中除去指定的成员。
- SISMEMBER 测试字符串的集合成员身份。
- SINTER 返回两个或多个集合(即交集)具有共同的成员集。
- SCARD 返回集合的大小(也称为基数)。
SADD 命令将新元素添加到集合中。这也是可能的 对集合执行许多其他操作,例如测试给定元素是否 已经存在,执行交集、并集或差值 多组,依此类推。
> SADD bikes:racing:beijing bike:1 bike:2 bike:3
(integer) 3
> SMEMBERS bikes:racing:beijing
1) bike:3
2) bike:1
3) bike:2
在这里,我在我的集合中添加了三个元素,并告诉 Redis 返回所有 元素。没有一套的订单保证。Redis 可以自由退货 元素在每次调用时按任意顺序排列。
Redis 具有用于测试集合成员资格的命令。这些命令可用于单个项目和多个项目:
> SISMEMBER bikes:racing:beijing bike:1
(integer) 1
> SMISMEMBER bikes:racing:beijing bike:2 bike:3 bike:4
1) (integer) 1
2) (integer) 1
3) (integer) 0
我们还可以找到两组之间的差异。例如,我们可能想要知道哪些自行车在北京比赛,但在上海比赛:
> SADD bikes:racing:shanghai bike:1 bike:4
(integer) 2
> SDIFF bikes:racing:beijing bikes:racing:shanghai
1) "bike:3"
2) "bike:2"
5.5.0 Sorted Set(有序集合)
Redis 排序集是按关联分数排序的唯一字符串(成员)的集合。 当多个字符串具有相同的分数时,这些字符串将按字典顺序排序。 排序集的一些用例包括:
- 排行榜。例如,您可以使用排序集来轻松维护大型在线游戏中最高分的有序列表。
- 速率限制器。具体而言,您可以使用排序集来构建滑动窗口速率限制器,以防止过多的 API 请求。
您可以将排序集视为 Set 和 Hash。与集合一样,排序集合由唯一的、不重复的集合组成 字符串元素,所以从某种意义上说,排序集合也是一个集合。
但是,虽然集合中的元素没有排序,但 排序集与浮点值相关联,称为分数(这就是为什么该类型也类似于哈希,因为每个元素 映射到值)。
此外,排序集合中的元素是按顺序获取的(因此它们不是 根据要求订购,订购是用于的数据结构的一个特点 表示排序集)。它们根据以下规则排序:
- 如果 B 和 A 是两个分数不同的元素,则 A > B,如果 A.score > B.score。
- 如果 B 和 A 的分数完全相同,则 A 字符串在词典上大于 B 字符串,则 A > B。B 和 A 字符串不能相等,因为排序集只有唯一的元素。
基本命令:
- ZADD 将新成员和关联的分数添加到排序集合中。如果该成员已存在,则分数将更新。
- ZRANGE 返回排序集合的成员,在给定范围内排序。
- ZRANK 返回所提供成员的等级,假设排序按升序排列。
- ZREVRANK 返回所提供成员的等级,假设排序集按降序排列。
让我们从一个简单的例子开始,我们将添加所有赛车手和他们在第一场比赛中获得的分数:
> ZADD racer_scores 10 "Norem"
(integer) 1
> ZADD racer_scores 12 "Castilla"
(integer) 1
> ZADD racer_scores 8 "Sam-Bodden" 10 "Royce" 6 "Ford" 14 "Prickett"
(integer) 4
ZADD 类似于 SADD,但需要一个额外的参数 (放在要添加的元素之前)即分数。ZADD 也是可变的,因此您可以自由指定多个分数值 对,即使上面的示例中没有使用。
使用排序集,返回按其排序的黑客列表是微不足道的 出生年份,因为实际上它们已经排序了。
实现说明:排序集是通过 包含跳过列表和哈希表的双端口数据结构,因此 每次添加元素时,Redis 都会执行 O(log(N)) 操作。那是 很好,但是当我们要求排序元素时,Redis 不必在 所有,它已经排序好了。请注意, ZRANGE 阶次从低到高,而 ZREVRANK 阶次从高到低:
> ZRANGE racer_scores 0 -1
1) "Ford"
2) "Sam-Bodden"
3) "Norem"
4) "Royce"
5) "Castilla"
6) "Prickett"
> ZREVRANGE racer_scores 0 -1
1) "Prickett"
2) "Castilla"
3) "Royce"
4) "Norem"
5) "Sam-Bodden"
6) "Ford"
5.6.0 Bitmaps(位图)
位图不是实际的数据类型,而是一组面向位的操作 在 String 类型上定义,该类型被视为位向量。 由于字符串是二进制安全 Blob,并且其最大长度为 512 MB, 它们适用于设置多达 2^32 个不同的位。
您可以对一个或多个字符串执行按位运算。 位图用例的一些示例包括:
- 对于集合成员对应于整数 0-N 的情况,有效的集合表示。
- 对象权限,其中每个位代表一个特定的权限,类似于文件系统存储权限的方式。
基本命令:
- SETBIT 在提供的偏移量处将位设置为 0 或 1。
- GETBIT 返回给定偏移量处的位值。
5.7.0 HyperLogLog(基数)
HyperLogLog类型是一种基数算法,用于估计一个集合中不同元素的数量。支持的操作包括添加元素、获取基数值等。
5.8.0 Geospatial(地理位置)
Geospatial类型是一种地理位置数据类型,用于存储地理位置信息和坐标。支持的操作包括添加位置信息、获取位置信息、计算位置之间的距离等。
基本命令:
- GEOADD 将位置添加到给定的地理空间索引中(请注意,使用此命令时,经度位于纬度之前)。
- GEOSEARCH 返回具有给定半径或边界框的位置。
5.9.0 Streams(流)
Redis 流是一种数据结构,其作用类似于仅追加日志,但也实现了多个操作,以克服典型仅追加日志的一些限制。这些包括 O(1) 时间的随机访问和复杂的消费策略,例如消费者组。 您可以使用流实时记录和同时联合事件。 Redis 流使用案例的示例包括:
- 事件来源(例如,跟踪用户操作、点击等)
- 传感器监控(例如,现场设备的读数)
- 通知(例如,将每个用户的通知记录存储在单独的流中)
Redis 为每个流条目生成一个唯一的 ID。 您可以使用这些 ID 稍后检索其关联的条目,或读取和处理流中的所有后续条目。请注意,由于这些 ID 与时间相关,因此此处显示的 ID 可能会有所不同,并且与您在自己的 Redis 实例中看到的 ID 不同。
Redis 流支持多种修整策略(以防止流无限增长)和多种消费策略(请参阅 XREAD、XREADGROUP 和 XRANGE)。
基本命令:
- XADD 向流添加新条目。
- XREAD 读取一个或多个条目,从给定位置开始并按时间向前移动。
- XRANGE 返回两个提供的条目 ID 之间的条目范围。
- XLEN 返回流的长度。
5.10.0 Modules(模块)
Redis支持动态加载模块,可以通过加载模块扩展 Redis 的功能,如添加新的数据类型、命令等。常见的 Redis 模块包括 RedisBloom、RedisTimeSeries、RedisJSON等。
不过最常用的就是前五种数据类型。