Redis - 字符串
Redis - 现代字符串操作
Section titled “Redis - 现代字符串操作”Redis 字符串是最简单的数据类型,但它们功能强大且用途广泛。它们是二进制安全的,这意味着一个字符串值可以容纳任何类型的数据,从 UTF-8 字符串到 JPEG 图像或序列化对象,最大可达 512MB。本节将介绍 Redis 中管理字符串值的现代命令和最佳实践。
1. 核心命令:SET、GET 和过期设置
Section titled “1. 核心命令:SET、GET 和过期设置”基本操作包括设置值、检索值以及管理其生命周期。现代 Redis 为了提高效率,将许多选项集中到 SET 命令中。
现代 SET 命令
Section titled “现代 SET 命令”与 SETEX 或 SETNX 等独立命令不同,现代 SET 命令包含的选项可以在一个单独的、原子性的操作中处理这些情况,从而减少网络延迟。
SET key value [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds] [NX | XX] [GET]EX seconds:设置以秒为单位的过期时间。PX milliseconds:设置以毫秒为单位的过期时间。NX:仅在键不存在时设置键。XX:仅在键已存在时设置键。GET:返回键的旧值,如果键不存在则返回 nil。
示例:缓存 API 响应
Section titled “示例:缓存 API 响应”# 设置用户会话数据,1 小时(3600 秒)后过期> SET session:user:123 "{...user data...}" EX 3600OK
# 尝试仅在用户名未被占用时设置> SET username:jane_doe "unique_user_id_123" NXOK # 成功,因为键是新的
> SET username:jane_doe "another_id_456" NX(nil) # 失败,因为键已存在
# 检索值> GET session:user:123"{...user data...}"2. 原子计数器和数值操作
Section titled “2. 原子计数器和数值操作”Redis 提供了用于递增或递减整数和浮点值的原子命令。‘原子性’意味着操作在不中断的情况下完全完成,这对于防止并发应用中的竞态条件(race conditions)至关重要(例如,多个客户端尝试更新同一个计数器)。
INCR key:将键的整数值递增 1。DECR key:将键的整数值递减 1。INCRBY key increment:将整数值递增给定数量。DECRBY key decrement:将整数值递减给定数量。INCRBYFLOAT key increment:将浮点值递增给定数量。
示例:API 端点限流
Section titled “示例:API 端点限流”# 用户发起请求。增加其请求计数器。> INCR api_limit:user:123:minute(integer) 1
# 首次对键设置过期时间,以便在一分钟后重置计数> EXPIRE api_limit:user:123:minute 60(integer) 1
# 更好的原子性实现方式是在事务或 Lua 脚本中使用 SET 和 INCR。
# 同一用户的另一个请求> INCR api_limit:user:123:minute(integer) 2
# 检查当前计数> GET api_limit:user:123:minute"2"3. 批量操作
Section titled “3. 批量操作”为减少网络往返(network round-trips),请使用 MSET 和 MGET 一次性设置或获取多个键。MSETNX 是一个变体,仅当所有键都不存在时才设置它们。
> MSET user:1:name "Alice" user:2:name "Bob" user:1:plan "premium"OK
> MGET user:1:name user:2:name user:3:name1) "Alice"2) "Bob"3) (nil) # user:3:name 未设置4. 位级操作(位图)
Section titled “4. 位级操作(位图)”位图允许你将字符串视为一个位数组。这对于追踪大量实体(entity)的布尔信息(例如,活跃/非活跃)来说,内存效率极高。
SETBIT key offset value:在offset处设置或清除位(0 或 1)。GETBIT key offset:返回offset处的位。BITCOUNT key [start end]:计算设置位(1)的数量。BITPOS key bit [start end]:查找第一个设置为 0 或 1 的位。
示例:追踪每日活跃用户
Section titled “示例:追踪每日活跃用户”# ID 为 5 的用户在 2023-10-27 登录> SETBIT daily_active_users:2023-10-27 5 1(integer) 0 # 该位之前为 0
# 用户 100 也登录> SETBIT daily_active_users:2023-10-27 100 1(integer) 0
# 用户 5 今天是否登录?> GETBIT daily_active_users:2023-10-27 5(integer) 1
# 今天有多少独立用户登录?> BITCOUNT daily_active_users:2023-10-27(integer) 25. 高级原子操作
Section titled “5. 高级原子操作”这些命令在一个原子步骤中执行操作并检索值。
GETSET key value:设置新值并返回旧值。适用于轮换密钥(secrets)或令牌(tokens)等场景。GETDEL key:检索键的值,然后将其删除。非常适合实现可靠的、一次性使用的消息队列或锁。APPEND key value:将值追加到字符串的末尾。返回字符串的新长度。
示例:处理任务
Section titled “示例:处理任务”# 任务存储在一个临时键中> SET task:job:987 "Process video upload"OK
# 一个工作进程原子性地获取任务详情并删除该键# 这确保没有其他工作进程能获取到相同的任务。> GETDEL task:job:987"Process video upload"最佳实践与常见用例
Section titled “最佳实践与常见用例”- 键命名: 使用清晰、分层的命名约定,例如
object:id:field(如user:1001:profile_pic)。这能提高可读性并防止键冲突(key collisions)。 - 缓存: 存储 API 响应、渲染后的 HTML 片段或复杂的计算结果。始终使用
EX设置过期时间,以防止数据过期或陈旧(stale data)。 - 会话存储: 存储用户会话数据。
EX选项非常适合在用户不活跃一段时间后自动登出用户。 - 限流: 在带有
EX的键上使用INCR来跟踪时间窗口内的操作。 - 功能开关: 一个简单的
GET feature:new_dashboard:enabled命令可以判断某个功能对用户或用户组是否启用。 - 避免大型负载: 尽管字符串可以容纳 512MB,但这通常是一种反模式(anti-pattern)。存储大型 JSON 文档最好通过 Redis 的原生 JSON 数据类型(RedisJSON 模块)或将数据拆分为 Redis 散列(Hash)来处理。