写在前面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类型大value5.2 Hash类型大value5.3 如何检测大value六、命令对比表6.1 String vs Hash命令对比6.2 场景选择建议七、面试高频考点Q1String和Hash存储对象如何选择Q2INCR命令有什么注意事项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 REDIS1.5 批量操作命令# 批量设置 mset key1 value1 key2 value2 key3 value3 # 批量获取 mget key1 key2 key3 # 批量设置原子操作任一失败则全部失败 msetnx key1 value1 key2 value2注意事项MGET返回的是数组不存在的key返回nilMSETNX是原子操作适合需要保证一致性的批量设置二、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, ex3600)缓存策略对比策略说明适用场景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 1002.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分布式锁注意事项设置过期时间防止死锁value使用唯一标识防止误删释放锁时验证value使用Lua保证原子性三、Hash命令详解3.1 基础操作命令实际场景Hash天生适合存储对象比StringJSON更灵活。# 设置单个字段 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:10013.2 字段管理命令# 删除字段 hdel user:1001 city # 检查字段是否存在 hexists user:1001 name # 仅当字段不存在时设置 hsetnx user:1001 email testexample.com # 获取字段数量 hlen user:10013.3 数值操作命令# 字段自增整数 hincrby user:1001 age 1 # 字段自增浮点数 hincrbyfloat user:1001 salary 1000.53.4 批量迭代命令# 迭代获取字段适合大Hash hscan user:1001 0 match field_* count 10四、Hash应用场景4.1 用户信息存储经验之谈用户信息用Hash存储可以只更新某个字段比StringJSON更高效。# 存储用户信息 hmset user:1001 name zhangsan age 25 city beijing email zhangsanexample.com # 只更新年龄 hset user:1001 age 26 # 只获取姓名和邮箱 hmget user:1001 name email # 检查邮箱是否存在 hexists user:1001 emailHash vs String存储对象对比对比项Hash存储StringJSON存储部分读取支持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 stock4.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字段数超过5000HGETALL操作耗时内存占用高解决方案# 拆分为多个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 05.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 f26.2 场景选择建议场景推荐类型理由简单KV缓存String简单高效对象存储字段多Hash支持部分读写计数器StringINCR原子操作分布式锁StringSET NX EX原子操作购物车Hashfield为商品IDvalue为数量用户SessionString整体存取带过期时间七、面试高频考点Q1String和Hash存储对象如何选择答案字段少5个且整体访问选String字段多或需要部分访问选Hash需要设置过期时间选StringHash不支持对单个field设置过期内存敏感选Hashziplist编码更省内存Q2INCR命令有什么注意事项答案value必须是整数格式否则报错key不存在时会初始化为0再自增范围是64位有符号整数超出范围会报错是原子操作高并发下安全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关键点使用SET NX EX原子加锁value使用唯一标识防止误删释放锁时验证value设置合理的过期时间八、参考资料Redis内存优化指南九、互动话题你在项目中遇到过String和Hash选型的困惑吗有没有因为选错类型导致的性能问题欢迎在评论区分享你的经验下一篇我们将深入探讨List和Set的命令细节与应用场景。
【Redis】字符串与哈希Day3(2026年)
发布时间:2026/5/30 9:40:45
写在前面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类型大value5.2 Hash类型大value5.3 如何检测大value六、命令对比表6.1 String vs Hash命令对比6.2 场景选择建议七、面试高频考点Q1String和Hash存储对象如何选择Q2INCR命令有什么注意事项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 REDIS1.5 批量操作命令# 批量设置 mset key1 value1 key2 value2 key3 value3 # 批量获取 mget key1 key2 key3 # 批量设置原子操作任一失败则全部失败 msetnx key1 value1 key2 value2注意事项MGET返回的是数组不存在的key返回nilMSETNX是原子操作适合需要保证一致性的批量设置二、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, ex3600)缓存策略对比策略说明适用场景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 1002.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分布式锁注意事项设置过期时间防止死锁value使用唯一标识防止误删释放锁时验证value使用Lua保证原子性三、Hash命令详解3.1 基础操作命令实际场景Hash天生适合存储对象比StringJSON更灵活。# 设置单个字段 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:10013.2 字段管理命令# 删除字段 hdel user:1001 city # 检查字段是否存在 hexists user:1001 name # 仅当字段不存在时设置 hsetnx user:1001 email testexample.com # 获取字段数量 hlen user:10013.3 数值操作命令# 字段自增整数 hincrby user:1001 age 1 # 字段自增浮点数 hincrbyfloat user:1001 salary 1000.53.4 批量迭代命令# 迭代获取字段适合大Hash hscan user:1001 0 match field_* count 10四、Hash应用场景4.1 用户信息存储经验之谈用户信息用Hash存储可以只更新某个字段比StringJSON更高效。# 存储用户信息 hmset user:1001 name zhangsan age 25 city beijing email zhangsanexample.com # 只更新年龄 hset user:1001 age 26 # 只获取姓名和邮箱 hmget user:1001 name email # 检查邮箱是否存在 hexists user:1001 emailHash vs String存储对象对比对比项Hash存储StringJSON存储部分读取支持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 stock4.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字段数超过5000HGETALL操作耗时内存占用高解决方案# 拆分为多个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 05.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 f26.2 场景选择建议场景推荐类型理由简单KV缓存String简单高效对象存储字段多Hash支持部分读写计数器StringINCR原子操作分布式锁StringSET NX EX原子操作购物车Hashfield为商品IDvalue为数量用户SessionString整体存取带过期时间七、面试高频考点Q1String和Hash存储对象如何选择答案字段少5个且整体访问选String字段多或需要部分访问选Hash需要设置过期时间选StringHash不支持对单个field设置过期内存敏感选Hashziplist编码更省内存Q2INCR命令有什么注意事项答案value必须是整数格式否则报错key不存在时会初始化为0再自增范围是64位有符号整数超出范围会报错是原子操作高并发下安全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关键点使用SET NX EX原子加锁value使用唯一标识防止误删释放锁时验证value设置合理的过期时间八、参考资料Redis内存优化指南九、互动话题你在项目中遇到过String和Hash选型的困惑吗有没有因为选错类型导致的性能问题欢迎在评论区分享你的经验下一篇我们将深入探讨List和Set的命令细节与应用场景。