当前位置: 首页 > news >正文

【Redis】字符串与哈希Day3(2026年)

写在前面

String和Hash是Redis中最常用的两种数据类型,掌握它们的命令细节和应用场景,能让你在实际开发中游刃有余。今天我们深入探讨这两种类型的核心命令与实战技巧。

文章目录

    • 写在前面
    • 一、String命令详解
      • 1.1 基础SET/GET命令
      • 1.2 带参数的SET命令
      • 1.3 数值操作命令
      • 1.4 字符串操作命令
      • 1.5 批量操作命令
    • 二、String应用场景
      • 2.1 缓存
      • 2.2 计数器
      • 2.3 分布式ID生成
      • 2.4 分布式锁
    • 三、Hash命令详解
      • 3.1 基础操作命令
      • 3.2 字段管理命令
      • 3.3 数值操作命令
      • 3.4 批量迭代命令
    • 四、Hash应用场景
      • 4.1 用户信息存储
      • 4.2 商品信息存储
      • 4.3 购物车实现
    • 五、踩坑提醒:value过大问题
      • 5.1 String类型大value
      • 5.2 Hash类型大value
      • 5.3 如何检测大value
    • 六、命令对比表
      • 6.1 String vs Hash命令对比
      • 6.2 场景选择建议
    • 七、面试高频考点
      • Q1:String和Hash存储对象如何选择?
      • Q2:INCR命令有什么注意事项?
      • Q3:如何实现一个分布式锁?
    • 八、参考资料
    • 九、互动话题

一、String命令详解

1.1 基础SET/GET命令

实际场景:SET/GET是最基础也是最常用的命令,但很多细节你可能不知道。

# 基本设置 set name "redis" # 基本获取 get name # 设置并返回旧值 getset name "new_redis" # 仅当key不存在时设置 setnx name "redis" # 仅当key存在时设置 set name "redis" xx

上述命令中,GETSET常用于原子性更新并获取旧值的场景;SETNX是分布式锁的基础;XX参数表示仅当key存在时才设置。

1.2 带参数的SET命令

# 设置过期时间(秒) set session:token "user_data" ex 3600 # 设置过期时间(毫秒) set session:token "user_data" px 3600000 # 设置过期时间戳(秒) set session:token "user_data" exat 1700000000 # NX参数:仅当key不存在时设置 set lock:order "uuid" nx ex 30 # GET参数:设置新值并返回旧值 set counter 100 get

注意事项

  • EX和PX不能同时使用
  • NX和XX不能同时使用
  • SET key value NX EX seconds 是原子操作,适合实现分布式锁

1.3 数值操作命令

经验之谈:Redis的数值操作是原子的,非常适合高并发计数场景。

# 设置数值 set counter 0 # 自增1 incr counter # 自增指定值 incrby counter 10 # 自增浮点数 incrbyfloat counter 2.5 # 自减1 decr counter # 自减指定值 decrby counter 5
命令说明返回值
INCR自增1自增后的值
INCRBY自增指定整数自增后的值
INCRBYFLOAT自增浮点数自增后的值
DECR自减1自减后的值
DECRBY自减指定整数自减后的值

注意事项

  • 如果key不存在,INCR会先初始化为0再自增
  • 如果value不是整数,INCR会报错
  • INCRBYFLOAT支持科学计数法

1.4 字符串操作命令

# 追加字符串 append name " tutorial" # 获取字符串长度 strlen name # 获取子字符串 getrange name 0 4 # 设置子字符串 setrange name 0 "REDIS"

1.5 批量操作命令

# 批量设置 mset key1 "value1" key2 "value2" key3 "value3" # 批量获取 mget key1 key2 key3 # 批量设置(原子操作,任一失败则全部失败) msetnx key1 "value1" key2 "value2"

注意事项

  • MGET返回的是数组,不存在的key返回nil
  • MSETNX是原子操作,适合需要保证一致性的批量设置

二、String应用场景

2.1 缓存

实际场景:缓存是Redis最常见的用途,能显著提升系统性能。

# 设置缓存(带过期时间) set cache:user:1001 '{"name":"zhangsan","age":25}' ex 3600 # 获取缓存 get cache:user:1001 # 缓存不存在时的处理(伪代码) # if redis.get(key) is None: # data = db.query(...) # redis.set(key, data, ex=3600)

缓存策略对比

策略说明适用场景
Cache Aside先查缓存,不存在再查库读多写少
Write Through写入时同时更新缓存读写均衡
Write Behind先写缓存,异步写库写多读少

2.2 计数器

# 文章阅读量 incr article:1001:views # 用户点赞数 incr user:1001:likes # 获取计数 get article:1001:views # 批量获取多个计数 mget article:1001:views article:1002:views

注意事项

  • 计数器不需要初始化,INCR自动创建
  • 高并发下INCR是原子操作,不会丢失计数

2.3 分布式ID生成

# 每天重置的ID set order:id:20240101 0 # 生成订单ID incr order:id:20240101 # 返回1,订单ID为:20240101000001 # 批量获取ID incrby order:id:20240101 100

2.4 分布式锁

踩坑提醒:分布式锁实现要考虑锁超时、误删等问题。

# 加锁(原子操作) set lock:order:1001 "uuid-xxx" nx ex 30 # 业务逻辑执行... # 释放锁(Lua脚本保证原子性) # if redis.call("get", KEYS[1]) == ARGV[1] then # return redis.call("del", KEYS[1]) # else # return 0 # end

分布式锁注意事项

  1. 设置过期时间,防止死锁
  2. value使用唯一标识,防止误删
  3. 释放锁时验证value,使用Lua保证原子性

三、Hash命令详解

3.1 基础操作命令

实际场景:Hash天生适合存储对象,比String+JSON更灵活。

# 设置单个字段 hset user:1001 name "zhangsan" # 设置多个字段 hmset user:1001 name "zhangsan" age 25 city "beijing" # 获取单个字段 hget user:1001 name # 获取多个字段 hmget user:1001 name age city # 获取所有字段和值 hgetall user:1001 # 获取所有字段名 hkeys user:1001 # 获取所有值 hvals user:1001

3.2 字段管理命令

# 删除字段 hdel user:1001 city # 检查字段是否存在 hexists user:1001 name # 仅当字段不存在时设置 hsetnx user:1001 email "test@example.com" # 获取字段数量 hlen user:1001

3.3 数值操作命令

# 字段自增整数 hincrby user:1001 age 1 # 字段自增浮点数 hincrbyfloat user:1001 salary 1000.5

3.4 批量迭代命令

# 迭代获取字段(适合大Hash) hscan user:1001 0 match "field_*" count 10

四、Hash应用场景

4.1 用户信息存储

经验之谈:用户信息用Hash存储,可以只更新某个字段,比String+JSON更高效。

# 存储用户信息 hmset user:1001 name "zhangsan" age 25 city "beijing" email "zhangsan@example.com" # 只更新年龄 hset user:1001 age 26 # 只获取姓名和邮箱 hmget user:1001 name email # 检查邮箱是否存在 hexists user:1001 email

Hash vs String存储对象对比

对比项Hash存储String+JSON存储
部分读取支持(HGET)需要整体读取
部分更新支持(HSET)需要整体更新
内存占用较小(ziplist)较大
字段查询支持(HEXISTS)需要解析JSON
适用场景字段多、部分访问字段少、整体访问

4.2 商品信息存储

# 存储商品信息 hmset product:2001 name "iPhone 15" price 6999 stock 100 category "phone" # 库存减1 hincrby product:2001 stock -1 # 获取库存 hget product:2001 stock # 获取商品基本信息 hmget product:2001 name price stock

4.3 购物车实现

# 添加商品到购物车 hset cart:user:1001 product:2001 2 hset cart:user:1001 product:2002 1 # 修改商品数量 hset cart:user:1001 product:2001 3 # 获取购物车所有商品 hgetall cart:user:1001 # 删除购物车商品 hdel cart:user:1001 product:2002 # 获取购物车商品数量 hlen cart:user:1001

五、踩坑提醒:value过大问题

踩坑提醒:大value是Redis性能杀手,务必控制value大小!

5.1 String类型大value

问题表现

  • 单个String value超过10KB
  • 网络传输慢,阻塞其他操作
  • 内存碎片增加

解决方案

# 方案1:压缩存储 # 将大对象压缩后存储 set big:object "compressed_data" ex 3600 # 方案2:拆分存储 set user:1001:profile "基本信息" set user:1001:detail "详细信息" set user:1001:settings "设置信息" # 方案3:使用Hash拆分 hmset user:1001 profile "基本信息" detail "详细信息" settings "设置信息"

5.2 Hash类型大value

问题表现

  • 单个Hash字段数超过5000
  • HGETALL操作耗时
  • 内存占用高

解决方案

# 拆分为多个Hash hmset user:1001:basic name "zhangsan" age 25 hmset user:1001:contact email "xxx" phone "xxx" hmset user:1001:address city "beijing" street "xxx" # 使用HSCAN迭代获取 hscan user:1001:basic 0

5.3 如何检测大value

# 使用redis-cli扫描大keyredis-cli--bigkeys# 查看指定key的内存占用redis-cli memory usage keyname# 使用RDB工具分析rdb--commandjson dump.rdb|python analyze.py

六、命令对比表

6.1 String vs Hash命令对比

操作String命令Hash命令
设置值SET key valueHSET key field value
获取值GET keyHGET key field
删除DEL keyHDEL key field
检查存在EXISTS keyHEXISTS key field
自增INCR keyHINCRBY key field num
批量设置MSET k1 v1 k2 v2HMSET key f1 v1 f2 v2
批量获取MGET k1 k2HMGET key f1 f2

6.2 场景选择建议

场景推荐类型理由
简单KV缓存String简单高效
对象存储(字段多)Hash支持部分读写
计数器StringINCR原子操作
分布式锁StringSET NX EX原子操作
购物车Hashfield为商品ID,value为数量
用户SessionString整体存取,带过期时间

七、面试高频考点

Q1:String和Hash存储对象如何选择?

答案

  • 字段少(<5个)且整体访问:选String
  • 字段多或需要部分访问:选Hash
  • 需要设置过期时间:选String(Hash不支持对单个field设置过期)
  • 内存敏感:选Hash(ziplist编码更省内存)

Q2:INCR命令有什么注意事项?

答案

  1. value必须是整数格式,否则报错
  2. key不存在时会初始化为0再自增
  3. 范围是64位有符号整数,超出范围会报错
  4. 是原子操作,高并发下安全

Q3:如何实现一个分布式锁?

答案

# 加锁(原子操作) set lock:resource "uuid" nx ex 30 # 释放锁(Lua脚本保证原子性) eval "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:resource "uuid"

关键点:

  1. 使用SET NX EX原子加锁
  2. value使用唯一标识防止误删
  3. 释放锁时验证value
  4. 设置合理的过期时间

八、参考资料

Redis内存优化指南


九、互动话题

你在项目中遇到过String和Hash选型的困惑吗?有没有因为选错类型导致的性能问题?欢迎在评论区分享你的经验!

下一篇我们将深入探讨List和Set的命令细节与应用场景。

http://www.rkmt.cn/news/1426816.html

相关文章:

  • 最新fastmoss优惠折扣码开通,fastmoss推荐码TK1000优惠是什么? - 跨境电商卖家出海官方
  • 从G题RockFrog到李超线段树:如何用动态开点解决特殊二次函数最值问题(附__int128防爆指南)
  • AD7606采样率上不去?STM32F4 SPI时序详解与定时器中断优化指南
  • AI智能体动态竞争评估:从静态测试到模拟市场的新范式
  • 别再只会用阿里源了!保姆级教程:Ubuntu 20.04/22.04 如何根据网络环境智能选择最快的镜像源
  • 2026 杭州全屋定制公司推荐|性价比高、工艺靠谱的本土定制品牌汇总 - 商业新知
  • Scarab:智能模组管理如何让《空洞骑士》游戏体验提升300%
  • 高效解决Honey Select 2兼容性问题的专业模组整合方案:HS2-HF Patch深度解析
  • 不止是升级:聊聊Intel i40e驱动更新对服务器网络性能的实际影响
  • 珍宝黄金回收|十年老店教你 2026 年 5 月大同黄金回收不吃亏 - 润富黄金珠宝行
  • AI写作内容如何通过GPTZero检测?人性化精修实战指南
  • 图片怎么去水印:全场景实操步骤与免费图片去水印工具完整汇总 - 科技热点发布
  • 汕头黄金回收必看!润富黄金回收教你 2026 年 5 月高位变现,无套路不扣重,全市免费上门 - 润富黄金珠宝行
  • 从模型堆放到沉浸体验:手把手教你用Unity的材质、光照和脚本,打造一个不“塑料”的VR工程展厅
  • 长沙哪家车衣贴膜机构好 - mypinpai
  • 余生黄金回收(全国连锁)2026年5月最新行情:金价992元/克,邯郸卖金避坑全攻略,六大门店免费上门当面称重不扣重 - 润富黄金珠宝行
  • Cursor插件大揭秘:多种开发工具类插件功能全解析!
  • 2026新疆HDPE管道厂家选型指南:本地源头直供、市政基建、非开挖工程全场景覆盖对比 - 企业名录优选推荐
  • 2026年汽车贴膜哪家口碑好? - mypinpai
  • 烟台一站式营销全案策划落地机构排行:实效维度对比 - 奔跑123
  • 告别懵圈!用5分钟搞懂SOME/IP的四种通信模式(附实战场景解析)
  • 别再只调包了!手撕SVM与BP神经网络,用MATLAB/Python复现健康数据分析全流程
  • 从ARIMA建模反推:为什么你的ADF检验结果总是不对?可能是这些预处理步骤没做好
  • KeyPhraseTransformer实战案例:如何用一行代码提取长文本中的关键主题?
  • 从零封装一个AS608的HAL库驱动:STM32CubeMX工程模板与可移植性设计详解
  • Stoic模型性能评估:准确预测蛋白质复合物组分比例的机器学习方法
  • nanowhale-100m的fp32精度要求:为什么bf16会导致NaN问题及解决方案
  • 从SENet到GCNet:一文读懂注意力机制如何进化成更轻量的全局上下文模块
  • 2026年新疆管道源头厂家深度选型指南|荣华装备科技与竞品全景对标 - 企业名录优选推荐
  • LiteParse:开源轻量 PDF 解析工具,多格式支持、多语言适配,功能强大!