Redis
Redis
一、Redis概述
1. 简介
Redis(Remote Dictionary Server)即远程字典服务,是一个开源的、基于内存的键值对存储数据库,使用 ANSI C 语言编写。
2. 特点
使用内存进行存储:
Redis将数据存储在内存中,使得数据的读写操作速度极快,理论上读取速度可达 110000 次/s,写速度可达 81000 次/s 。同时,Redis也支持将数据持久化到磁盘,以便在服务器重启后数据不丢失。数据类型丰富:
Redis 支持多种数据类型,包括字符串(String)、列表(List)、集合(Set)、有序集合(Sorted Set 或 ZSet)、哈希(Hash)、位图(Bitmap)、超日志(HyperLogLog)以及地理空间(Geospatial)等。主从同步
Redis 支持主从复制模式(master - slave),数据可以从主服务器向任意数量的从服务器同步。这种机制不仅可以实现数据备份,提高数据安全性,还能通过从服务器分担读操作压力,提升系统整体的并发处理能力。多语言支持:
Redis 提供了对多种编程语言的支持,如 C、C++、Python、Java、PHP、Ruby、Lua 等。自带多个数据库
与传统 SQL 型数据库不同,Redis 默认自带 16 个数据库(编号从 0 到 15),默认使用 0 号数据库。在同一个数据库中,键(key)是唯一的,通过键值对的方式存储和检索数据。
二、Redis 数据类型
1. 字符串(String)
结构与特点
字符串是 Redis 最基本的数据类型,它可以存储任意类型的字符串,包括普通文本、二进制数据(如图片、音频的二进制编码)等。在内部实现上,Redis 的字符串采用简单动态字符串(Simple Dynamic String,SDS)结构,这种结构相比于传统的 C 字符串,在字符串操作的效率和内存管理方面有明显优势,例如在进行字符串拼接时,SDS 可以避免频繁的内存重新分配操作。常用命令
SET key value
设置指定键的值。例:SET mykey "Hello" 。GET key
获取指定键的值。例:GET mykey将返回"Hello" 。APPEND key value
向指定键对应的值后面追加字符串,如果键不存在,则相当于执行SET操作,如APPEND mykey ", World" ,执行后mykey的值变为"Hello, World" 。STRLEN key
获取指定键对应字符串的长度,例如STRLEN mykey返回11 。INCR key和DECR key
对存储数字值的字符串进行自增和自减操作,如果键不存在,则会先初始化为 0 再进行操作。如SET views 0 ,然后INCR views ,views的值变为1 ;DECR views后,views的值变回0 。还可以使用INCRBY key increment和DECRBY key decrement指定增减的步长。GETRANGE key start end
截取字符串,例如GETRANGE mykey 0 4会返回"Hello" 。SETEX key seconds value
设置键值并指定过期时间(单位为秒),如SETEX mykey 60 "Hello"表示mykey的值为"Hello" ,60 秒后该键值对会自动过期删除。SETNX key value
“SET if Not eXists”,只有当键不存在时才设置键值,常用于实现分布式锁等场景。若设置成功返回1 ,键已存在则返回0 。
2. 列表(List)
结构与特点
Redis 的列表是一个有序的字符串元素集合,可以在列表的头部(左边)或尾部(右边)插入或删除元素。
列表的底层实现有两种:压缩列表(ziplist)和快速链表(quicklist)。当列表元素较少且每个元素长度较短时,Redis 会使用压缩列表存储,以节省内存空间;当列表元素较多或元素长度较长时,则会切换为快速链表。快速链表结合了链表和数组的优点,既便于在两端进行插入和删除操作,又能在一定程度上提高内存利用率和访问效率。常用命令
LPUSH key value1 [value2...]
将一个或多个值插入到列表头部,例如LPUSH mylist "Hello" "World" ,此时mylist的元素顺序为["World", "Hello"]。RPUSH key value1 [value2...]
将一个或多个值插入到列表尾部,如RPUSH mylist "Redis",mylist变为["World", "Hello", "Redis"]。LPOP key
移除并返回列表头部的元素,执行LPOP mylist后,mylist变为["Hello", "Redis"] ,并返回"World"。RPOP key
移除并返回列表尾部的元素,RPOP mylist会使mylist变为["Hello"] ,并返回"Redis"。LRANGE key start stop
获取列表指定范围内的元素,索引从 0 开始,-1表示最后一个元素。例如LRANGE mylist 0 -1将返回["Hello"],即返回整个列表的所有元素。
3. 集合(Set)
结构与特点
集合是一个无序的、不包含重复元素的字符串集合。Redis 集合的底层实现有两种:当集合中的元素都是整数且元素数量较少时,使用整型数组存储;当元素不满足上述条件时,使用字典哈希表存储。集合的无序性和元素唯一性使得它在很多场景下非常有用,例如去重、交集、并集、差集等集合运算操作。常用命令
SADD key member1 [member2...]
向集合中添加一个或多个元素,例如SADD myset "Apple" "Banana" 。如果元素已存在,则不会重复添加,返回 0;新添加元素则返回1。SMEMBERS key
返回集合中的所有元素,如SMEMBERS myset可能返回["Apple", "Banana"](顺序不确定)。SISMEMBER key member
判断一个元素是否在集合中,存在返回1 ,不存在返回0 ,例如SISMEMBER myset "Apple"返回1。SCARD key
获取集合中元素的数量,SCARD myset返回2。SINTER key1 [key2...]
返回多个集合的交集,假设有另一个集合set2包含["Banana", "Cherry"],SINTER myset set2将返回["Banana"]。SUNION key1 [key2...]
返回多个集合的并集,SUNION myset set2可能返回["Apple", "Banana", "Cherry"](顺序不确定)。SDIFF key1 [key2...]
返回第一个集合与其他集合的差集,SDIFF myset set2将返回["Apple"] 。
4. 有序集合(Sorted Set / ZSet)
结构与特点
有序集合是在集合的基础上,为每个元素关联了一个分数(score),通过分数对元素进行从小到大排序。有序集合的底层实现结合了压缩列表(当元素较少且分数为整数时)和跳表(skiplist)与哈希表(当元素较多或分数为浮点数等复杂情况时)。跳表是一种随机化的数据结构,它在链表的基础上增加了多层索引,使得查找、插入和删除操作的时间复杂度接近平衡二叉树,平均为O(log n),大大提高了有序集合操作的效率。常用命令
ZADD key score1 member1 [score2 member2...]
向有序集合中添加一个或多个元素及其对应的分数,例如ZADD myzset 1 "Apple" 2 "Banana"。ZRANGE key start stop [WITHSCORES]
返回有序集合中指定范围内的元素,默认按分数从小到大排序。如果指定WITHSCORES,则会同时返回元素及其对应的分数,如ZRANGE myzset 0 -1 WITHSCORES可能返回[["Apple", 1], ["Banana", 2]] 。ZREVRANGE key start stop [WITHSCORES]
与ZRANGE类似,但返回的元素按分数从大到小排序。ZSCORE key member
获取指定元素在有序集合中的分数,ZSCORE myzset "Apple"返回1。ZINCRBY key increment member
为指定元素的分数增加指定的增量,如ZINCRBY myzset 1 "Apple" ,执行后"Apple"的分数变为2。ZCARD key
获取有序集合中元素的数量,ZCARD myzset返回2。ZCOUNT key min max
统计有序集合中分数在指定范围内的元素数量,例如ZCOUNT myzset 1 2返回2。
5. 哈希(Hash)
结构与特点
哈希类型用于存储键值对的集合,其中每个键值对中的值可以是字符串类型。哈希的底层实现同样有压缩列表(当哈希元素较少且键值对长度较短时)和字典哈希表(当元素较多或键值对长度较长时)两种方式。这种数据类型非常适合存储对象,例如可以将用户信息(用户名、年龄、邮箱等)以哈希的形式存储在 Redis 中,每个字段作为哈希的一个键,对应的值为用户的实际信息。常用命令
HSET key field value
为哈希表中的指定字段设置值,例如HSET myhash field1 "Hello"。HGET key field
获取哈希表中指定字段的值,HGET myhash field1返回"Hello"。HGETALL key
返回哈希表中的所有字段和值,HGETALL myhash可能返回["field1", "Hello"]。HDEL key field1 [field2...]
删除哈希表中的一个或多个字段,HDEL myhash field1将删除field1及其对应的值。HEXISTS key field
判断哈希表中是否存在指定字段,存在返回1 ,不存在返回0 ,如HEXISTS myhash field1返回1。HINCRBY key field increment
为哈希表中指定字段的值增加指定的增量,假设HSET myhash age 20 ,执行HINCRBY myhash age 1后,age字段的值变为21。HLEN key
获取哈希表中字段的数量,HLEN myhash返回1。
6. 位图(Bitmap)
结构与特点
位图并不是一种真正的数据类型,而是基于字符串类型实现的一种数据结构,它将字符串看作是由一个个二进制位组成的数组。每个二进制位(0 或 1)可以表示一个状态,例如可以用位图来统计用户的登录状态(登录为 1,未登录为 0)、用户对某个功能的使用情况(使用为 1,未使用为 0)等。由于位图是按位存储,所以在存储大量布尔值类型的数据时,非常节省内存空间。常用命令
SETBIT key offset value
设置位图中指定偏移量(offset)处的二进制位的值,例如SETBIT mybitmap 0 1表示将mybitmap的第0位设置为1。GETBIT key offset
获取位图中指定偏移量处的二进制位的值,GETBIT mybitmap 0返回1。BITCOUNT key [start end]
统计位图中指定范围内(默认统计整个位图)值为1的二进制位的数量,如BITCOUNT mybitmap返回1。
7. 超日志(HyperLogLog)
结构与特点:
超日志是一种用于近似计算集合中唯一元素数量的数据结构。它通过牺牲一定的精度来换取极低的内存占用,适合在不需要精确统计唯一元素数量,而只关注大致数量级的场景下使用,例如统计网页的 UV(Unique Visitor,独立访客数)。HyperLogLog 的原理基于概率算法,通过对输入数据的哈希值的特定位进行统计来估算唯一元素的数量。常用命令
PFADD key element1 [element2...]
向 HyperLogLog 中添加一个或多个元素,例如PFADD myhyperloglog "Apple" "Banana"。PFCOUNT key
返回 HyperLogLog 中估算的唯一元素数量,PFCOUNT myhyperloglog返回一个近似值。PFMERGE destkey sourcekey1 [sourcekey2...]
将多个 HyperLogLog 合并为一个,结果存储在destkey中,例如PFMERGE newhyperloglog myhyperloglog1 myhyperloglog2。
8. 地理空间(Geospatial)
结构与特点
地理空间类型是 Redis 3.2 版本后新增的数据类型,用于存储地理位置信息,并提供了一系列基于地理位置的操作。它通过有序集合(Sorted Set)来实现,将地理位置的经纬度信息映射为有序集合中的元素和分数,从而可以高效地进行地理位置的查询和计算,如查询某个位置附近的其他位置、计算两个位置之间的距离等。常用命令
GEOADD key longitude latitude member [longitude latitude member...]
将一个或多个地理位置信息添加到指定键中,例如GEOADD cities 116.40 39.90 "Beijing" 121.47 31.23 "Shanghai"。GEOPOS key member1 [member2...]
获取指定地理位置元素的经纬度,GEOPOS cities "Beijing"返回[116.40, 39.90]GEODIST key member1 member2 [unit]
计算两个地理位置元素之间的距离,unit参数可以指定距离单位,如m(米)、km(千米)等,GEODIST cities "Beijing" "Shanghai" km返回北京和上海之间的大致距离(单位为千米)。GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
以指定的经纬度为中心,查询指定半径范围内的地理位置元素。WITHCOORD表示返回结果中包含元素的经纬度,WITHDIST表示返回结果中包含元素到中心位置的距离,WITHHASH表示返回结果中包含元素的地理位置哈希值,COUNT count表示限制返回结果的数量。例如GEORADIUS cities 116.40 39.90 1000 km WITHCOORD WITHDIST会返回距离北京 1000 千米范围内的城市及其经纬度和到北京的距离。
三、Redis 事务
1. 事务的概念与作用
Redis 事务是一个单独的隔离操作,它允许将多个命令组合在一起,保证这些命令作为一个整体被顺序执行。在事务执行过程中,不会被其他客户端发送的命令请求所中断。事务的主要作用是确保一系列操作的原子性(在 Redis 中,原子性指事务中的命令要么全部执行成功,要么全部不执行),并且可以防止其他命令插队执行,从而保证数据的一致性和完整性。例如,在一个电商系统中,当用户进行购买操作时,可能需要同时更新商品库存、记录订单信息等多个操作,使用事务可以确保这些操作要么全部成功,使交易正常完成;要么全部失败,避免出现部分操作成功导致的数据不一致问题,如商品库存已减少但订单未记录的情况。
2. 事务相关命令
- MULTI
用于开启一个事务,它会将后续的命令放入队列中,直到遇到EXEC命令才开始执行队列中的所有命令。 - EXEC
执行事务队列中的所有命令,在执行EXEC之前,事务中的命令只是被缓存起来,并不会实际执行。一旦执行EXEC ,Redis 会顺序执行队列中的每个命令,并返回每个命令的执行结果。 - DISCARD
放弃事务,清空事务队列,相当于事务回滚,它会取消正在进行的事务,队列中的所有命令都不会被执行。 - WATCH key [key ...]
在事务开始前监控一个或多个键,当调用EXEC执行事务时,如果监控的键在事务开启后被其他客户端修改,该事务会被打断,EXEC返回nil,从而避免脏读问题。
3. 事务执行流程
开启事务:客户端发送MULTI命令,进入事务状态。
命令入队:后续的命令会被存入事务队列,不会立即执行,返回QUEUED表示命令已入队。
执行事务:发送EXEC命令,Redis 按顺序执行队列中的所有命令,并返回结果集。
事务结束:执行完毕后,Redis 退出事务状态。
4. 事务的特性
- 原子性
Redis 事务中的命令要么全部执行,要么全部不执行(除非在命令入队时发生语法错误,此时事务会直接失败)。但需注意:如果事务执行过程中某个命令执行失败(如类型错误),其他命令仍会继续执行,这与传统数据库的强原子性不同。 - 一致性
事务执行前后,数据始终保持合法状态(如不会出现库存为负数的情况)。 - 隔离性
事务执行时不会被其他事务打断,保证命令按顺序执行。 - 持久性
若开启持久化(如 RDB 或 AOF),事务执行结果会被持久化到磁盘。
5. 事务与 WATCH 的使用示例
场景:实现简单的库存扣减(避免超卖)
127.0.0.1:6379> WATCH inventory # 监控库存键
OK
127.0.0.1:6379> GET inventory
"10" # 当前库存为10
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> DECR inventory # 扣减库存(入队)
QUEUED
127.0.0.1:6379> EXEC # 执行事务
1) "9" # 执行成功,库存变为9
# 若其他客户端在事务执行前修改了inventory:
# 客户端1: WATCH inventory -> MULTI -> DECR inventory -> 等待EXEC
# 客户端2: SET inventory "5" # 修改库存
# 客户端1: EXEC # 事务被打断,返回nil
(nil)
四、Redis 持久化机制
1. RDB(Redis Database)
定义与原理
RDB 是 Redis 默认的持久化方式,它通过将当前数据库的数据快照保存到磁盘来实现持久化。RDB 文件是一个二进制文件,结构紧凑,适合用于数据备份和全量恢复。触发方式
自动触发:根据redis.conf中的配置规则触发,例如:
save 900 1 # 900秒内至少1个键被修改时触发 save 300 10 # 300秒内至少10个键被修改时触发 save 60 10000 # 60秒内至少10000个键被修改时触发
手动触发:执行SAVE(阻塞主线程)或BGSAVE(fork 子进程执行,不阻塞主线程)命令。
优缺点
- 优点:
- 文件体积小,恢复速度快,适合全量备份。
- 生成 RDB 文件时主进程唯一的开销是 fork 子进程,性能影响较小。
- 缺点:
- 数据安全性较低,两次快照之间的数据可能丢失(如宕机时距离上次快照 5 分钟,则这 5 分钟的数据丢失)。
- fork 子进程时会消耗内存(Copy-on-Write 机制优化,但大内存实例仍有压力)。
- 优点:
2. AOF(Append Only File)
定义与原理
AOF 通过记录 Redis 服务器执行的每一条写命令来实现持久化,这些命令以文本形式追加到 AOF 文件末尾。Redis 重启时,会重新执行 AOF 文件中的命令来恢复数据。写入策略
AOF 的写入和同步磁盘的策略由appendfsync配置控制:- always:每条写命令都同步到磁盘,数据安全性最高,但性能最差。
- everysec:每秒同步一次磁盘,兼顾性能和安全性(默认配置)。
- no:由操作系统决定何时同步,性能最好,但数据安全性最低。
AOF 重写(Rewrite)
- AOF 文件会随着写命令的累积而越来越大,Redis 提供BGREWRITEAOF命令用于重写 AOF 文件。
- 原理:通过读取当前数据库的数据,重新生成一个简化的 AOF 文件(如合并INCR命令),避免文件过大。
- 触发方式:自动触发(根据auto-aof-rewrite-percentage和auto-aof-rewrite-min-size配置)或手动触发。
优缺点
- 优点:
- 数据安全性高,可配置always策略实现几乎不丢数据。
- AOF 文件是文本格式,可直接查看和修改(用于数据修复)。
- 缺点:
- 文件体积通常比 RDB 大,恢复速度较慢。
- 频繁写入时,always策略会影响性能。
- 优点:
3. RDB 与 AOF 对比与选择
特性 | RDB | AOF |
---|---|---|
数据安全性 | 可能丢失最后一次快照后的数据 | 取决于写入策略,always几乎不丢 |
文件体积 | 小(二进制压缩) | 大(文本命令记录) |
恢复速度 | 快 | 慢 |
性能影响 | 仅在fork时消耗资源 | 取决于写入策略,always影响大 |
适用场景 | 备份、全量恢复、读多写少 | 数据安全性要求高、写频繁 |
建议配置:同时开启 RDB 和 AOF,RDB 用于定期全量备份,AOF 用于实时数据安全,优先使用 AOF 恢复(数据更完整)。
五、Redis 主从复制(Master-Slave)
1. 基本概念
- 主从复制是 Redis 的核心特性之一,允许将数据从主服务器(Master)自动复制到一个或多个从服务器(Slave):
- 主服务器负责处理写操作,并将数据变更同步给从服务器。
- 从服务器默认只读,可用于分担读压力(如查询操作)。
2. 配置方式
修改从服务器配置:在redis.conf中添加:
slaveof <master_ip> <master_port> # 例如:slaveof 192.168.1.100 6379
启动后生效:从服务器启动时会自动连接主服务器并同步数据。
动态配置:也可通过命令SLAVEOF <master_ip> <master_port>动态设置主服务器。
3. 复制流程
初次同步:
- 从服务器向主服务器发送SYNC命令。
- 主服务器执行BGSAVE生成 RDB 文件,并将文件发送给从服务器。
- 从服务器接收 RDB 文件并加载数据,同时缓存主服务器在此期间的写命令。
- RDB 加载完成后,主服务器将缓存的写命令发送给从服务器,完成同步。
增量同步:
初次同步后,主服务器会将新的写命令通过缓冲区持续发送给从服务器,保持数据一致。
4. 主从复制的作用
- 读写分离
从服务器处理读请求,主服务器处理写请求,提升系统并发能力。 - 数据备份
从服务器作为主服务器的热备,主服务器宕机时可手动切换(或通过哨兵模式自动切换)。 - 故障恢复
通过从服务器快速恢复数据,避免主服务器单点故障。
5. 哨兵模式(Sentinel)
定义与作用
哨兵模式是 Redis 的高可用性解决方案,它通过一组哨兵节点(Sentinel)监控主从集群:- 监控:实时监控主服务器和从服务器的运行状态。
- 通知:当主服务器出现故障时,向其他哨兵和客户端发送通知。
- 自动故障转移:选举新的主服务器,并将从服务器指向新主服务器。
配置示例
- 创建sentinel.conf配置文件:
sentinel monitor mymaster 192.168.1.100 6379 2 # 监控主服务器,2表示至少2个哨兵同意才进行故障转移 sentinel down-after-milliseconds mymaster 5000 # 主服务器5秒无响应则判定为下线 sentinel failover-timeout mymaster 60000 # 故障转移超时时间
- 启动哨兵:redis-sentinel sentinel.conf
六、Redis 集群(Cluster)
1. 分布式架构概述
- Redis 集群是 Redis 3.0 后引入的分布式解决方案,解决了单机 Redis 的内存限制和单点故障问题,具有以下特点:
- 数据分片:将数据分散存储在多个节点(Node)中,每个节点负责一部分数据。
- 高可用性:通过主从复制和自动故障转移,确保集群在部分节点故障时仍能正常工作。
- 水平扩展:可通过添加节点来扩展集群的存储容量和处理能力。
2. 数据分片机制(哈希槽)
- Redis 集群使用哈希槽(Hash Slot)来实现数据分片。
- 集群共有 16384 个哈希槽(0~16383),每个键通过CRC16(key) % 16384计算所属的槽。
- 每个节点负责一部分哈希槽,例如 3 节点集群可能每个节点负责约 5461 个槽。
- 当添加或删除节点时,集群会自动迁移哈希槽和数据,保持负载均衡。
3. 集群搭建(三主三从)
- 配置节点:每个节点的redis.conf需开启集群模式:
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
- 使用redis-cli --cluster工具创建集群:
redis-cli --cluster create \
192.168.1.100:7000 192.168.1.101:7001 192.168.1.102:7002 \
192.168.1.100:7003 192.168.1.101:7004 192.168.1.102:7005 \
--cluster-replicas 1 # 每个主节点配1个从节点
集群创建后,客户端可连接任意节点,自动重定向到目标节点。
4. 集群的优势与应用场景
- 优势:
- 突破单机内存限制,支持 TB 级数据存储。
- 高可用性,自动故障转移,避免单点故障。
- 读写性能线性扩展,适合高并发场景。
- 场景:
- 大型电商的商品缓存、用户会话存储。
- 社交平台的点赞、粉丝关系存储。
- 实时分析系统的计数和统计数据。
七、Redis 应用场景
1. 缓存(最典型场景)
- 实现方式
将数据库中查询频率高的数据存入 Redis,减少数据库压力。 - 注意事项:
- 设置合理的过期时间,避免缓存雪崩。
- 采用 “缓存击穿” 解决方案(如互斥锁、热点数据永不过期)。
- 示例:
import redis
import mysql.connector
r = redis.Redis(host='localhost', port=6379, db=0)
db = mysql.connector.connect(host='localhost', user='root', password='', database='mydb')
def get_user_info(user_id):
# 先查缓存
key = f"user:{user_id}"
user = r.get(key)
if user:
return eval(user)
# 缓存未命中,查数据库
cursor = db.cursor()
cursor.execute(f"SELECT * FROM users WHERE id={user_id}")
user = cursor.fetchone()
if user:
# 写入缓存,过期时间3600秒
r.setex(key, 3600, str(user))
return user
2. 计数器与限速
计数器:利用 Redis 的原子性操作(如INCR)实现高并发计数,例如:
文章阅读量、点赞数:INCR post:123:views
全局唯一ID:INCR global:id限速(Rate Limiting):通过INCR和EXPIRE实现访问频率限制,例如限制用户每分钟最多访问 10 次:
127.0.0.1:6379> INCRBY user:123:access:20230611:14 1 # 记录当前分钟的访问次数
(integer) 1
127.0.0.1:6379> EXPIRE user:123:access:20230611:14 60 # 设置过期时间60秒
(integer) 1
127.0.0.1:6379> GET user:123:access:20230611:14
"10" # 当次数超过10时,拒绝访问
3. 消息队列(轻量级)
- 基于 List 的队列:使用LPUSH和RPOP实现先进先出(FIFO)队列:
生产者:LPUSH queue:task "job1"
消费者:RPOP queue:task - 阻塞队列:使用BRPOP实现阻塞式读取,无数据时消费者阻塞等待:
127.0.0.1:6379> BRPOP queue:task 0 # 0表示无限等待
1) "queue:task"
2) "job1"
4. 分布式锁
- 实现方式:利用 Redis 的SETNX和EXPIRE命令实现。
127.0.0.1:6379> SET lock:resource 123456 NX PX 30000 # NX表示仅当锁不存在时获取,PX 30000设置过期时间30秒
OK # 获得锁,值为随机数(用于释放锁时验证)
处理业务逻辑...
127.0.0.1:6379> IF GET lock:resource == 123456 THEN DEL lock:resource # 释放锁时先验证
Redlock 算法:在分布式环境下通过多个 Redis 实例实现更可靠的分布式锁,避免单点故障。
5. 社交关系与排行榜
- 社交关系:
- 粉丝列表:使用 Set 存储用户的粉丝(SADD user:123:followers 456)
- 共同好友:使用SINTER计算两个用户的共同粉丝
- 排行榜:利用 Sorted Set 按分数排序,例如游戏得分排行榜。
127.0.0.1:6379> ZADD leaderboard 95 "user1" 88 "user2" 92 "user3"
(integer) 3
127.0.0.1:6379> ZREVRANGE leaderboard 0 2 WITHSCORES # 按分数