文章

redis常见命令

hash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HDEL hash:jd:goods:sync_tag 66d280dfdde84a769c2550b
HSET hash:jd:goods:sync_tag 66d280dfdde84a769c2550b "2025-05-16 11:38:38"
HSET user:profile:10086 name "张三" age 29 vip 1
┌------------------------------------------┐
│ user:profile:10086                       │
│  ┌----------┬------------------------┐   │
│  │ field    │ value                  │   │  
│  ├----------┼------------------------┤   │  
│  │ name     │ "张三"                 │   │
│  │ age      │ "29"                   │   │
│  │ vip      │ "1"                    │   │
│  │ avatar   │ "https://a.com/1.jpg"  │   │
│  └----------┴------------------------┘   │
└------------------------------------------┘ 
HGET user:profile:10086 name               → "张三"
HGETALL user:profile:10086                 → 整个字典
HDEL user:profile:10086 vip                → 删除 vip 字段

string

1
2
set token_xhs_64ddfb481f385f0001c295aa xxx 存
get token_xhs_64ddfb481f385f0001c295aa 取

• Hash 像“表里的一行多列”,field 就是列名。 • String 像“键对应一个格子”,格子里可以是字符串、数字、JSON、二进制,什么都行。

1
2
3
4
┌-----------------------------------┐
│ cache:ip_whitelist                │    键 cache:ip_whitelist 
│ value = "192.168.1.0/24,10.0.0.1" │    值 "192.168.1.0/24,10.0.0.1"
└-----------------------------------┘

过期时间

1
2
// 原子一条命令 h.Config.MyRedis.DoWithContext(ctx, "SETEX", key, 300, strconv.FormatBool(isOn))
// 或者 h.Config.MyRedis.DoWithContext(ctx, "SET", key, strconv.FormatBool(isOn), "EX", 300)
维度SETEXSET … EX …
原子性单命令原子单命令原子(只要写在一条里)
参数顺序SETEX key seconds valueSET key value EX seconds
是否必带过期间必须带可选
出现版本1.0 就有2.6.12 才支持 EX/PX/NX/XX 扩展参数
返回值简单字符串 "OK"同上
客户端封装部分老客户端只暴露 SETEX,没有 EX 参数新客户端推荐统一用 SET + 扩展参数

list

1
2
3
4
5
6
7
key := "openuid_to_order_queue:user_123456"
client.DoWithContext(ctx, "RPUSH", key, "order_789012") // 存
client.DoWithContext(ctx, "EXPIRE", key, DefaultExpiration)

msgs, err := client.LRange(ctx, key, 0, -1).Result() // 取 //先进先出
//如果后续继续添加新的订单消息,例如 "order_345678",那么 Redis 的列表会更新为:
//"openuid_to_order_queue:user_123456" -> ["order_789012", "order_345678"]

命令行

1
2
3
RPUSH openuid_to_order_queue:user_123456 order_789012  //存
EXPIRE openuid_to_order_queue:user_123456 <DefaultExpiration>  
LRANGE openuid_to_order_queue:user_123456 0 -1   //取

img

  1. 操作性质不同 OrderMissBuyerIDRead - 需要原子性操作: 需要同时执行 LRANGE(读取)和 LTRIM(删除已读取的元素) 这两个操作必须在同一个原子事务中完成,否则可能出现: 读取了数据但没有删除 或者删除操作失败导致数据丢失 SafeGetAllOrderMsgsByOrderID - 只是读取操作: 只执行 LRANGE 读取所有数据 不删除数据,所以不需要原子性保证
  2. 并发安全性考虑 OrderMissBuyerIDRead: 多个消费者可能同时读取同一个队列 使用管道确保读取和删除的原子性,避免重复消费 没有分布式锁保护,所以需要Redis层面的原子性 SafeGetAllOrderMsgsByOrderID: 有分布式锁保护(withDistributedLock) 同一时间只有一个进程能访问该订单的消息队列 所以不需要Redis层面的原子性操作
  3. 使用场景不同 OrderMissBuyerIDRead: 用于批量处理待补全订单 需要确保每个订单ID只被处理一次 类似消息队列的消费模式 SafeGetAllOrderMsgsByOrderID: 用于获取特定订单的所有缓存消息 获取后通常会删除整个队列(通过 SafeDeleteAllOrderMsgsByOrderID) 类似缓存读取模式 总结 使用管道批量操作的原因: 原子性:确保读取和删除操作要么都成功,要么都失败 性能:减少网络往返次数 并发安全:避免多消费者场景下的数据竞争问题 而 SafeGetAllOrderMsgsByOrderID 不需要管道是因为: 只有读取操作,没有删除操作 有分布式锁保护,不存在并发问题 读取后通常会删除整个队列,所以不需要部分删除 这种设计是合理的,符合各自的使用场景和并发需求。

set

SADD 命令,用于向一个 Set(集合) 中添加一个或多个成员

1
SADD "sdk-jd:shopnicks:6257cba333615f0019b1be56" "几素官方旗舰店"

将店铺昵称 “几方旗舰店” 添加到集合 “sdk-jd:shopnicks:6257cba333615f]0019b1be56” 中。 如果该昵称已存在,集合不会改变(Set 自动去重)。 如果该昵称不存在,则添加成功。

1
SMEMBERS "sdk-jd:shopnicks:6257cba333615f0019b1be56"

© 2024- lfj