Redis的String类型是底层基于简单动态字符串实现的最基础数据结构,不仅能保存文本,也能以二进制安全方式存放序列化对象、数值或图片摘要。理解它的常用命令,是搭建缓存、计数器与分布式锁的前提。不同于关系型数据库的字段更新,Redis的String覆盖写会直接替换原值,因此在使用时需要明确是新建还是追加。

基础读写与批量操作命令
最基础的写入命令是SET,它可以附带过期时间参数,例如SET key value EX 60表示写入后六十秒自动删除。与之对应的是GET,当键不存在时返回空值而非报错,这一点和某些语言中的字典取值不同,需要在业务代码里做空判断。如果只想在键不存在时写入,可以使用SETNX,它是实现分布式锁的最简单原型,但单条命令无法同时设置过期时间,老版本中容易因进程崩溃造成死锁,因此新版本推荐用SET key value NX EX 30的复合写法。
当面临一次性写入多个配置项的场景,逐条SET会产生多次网络往返。此时MSET与MGET能够将多个键值对打包,在服务端原子执行。下面的示例展示批量写入与读取:
# 批量设置 MSET user:1:name 张三 user:1:age 28 user:2:name 李四 # 批量获取 MGET user:1:name user:1:age user:2:name
需要注意,MSET也是覆盖写,如果其中某个键已存在,它的值会被无声替换。在配置中心类应用中,若希望保留旧值并合并,就不能直接使用该命令,而应先读取再计算。此外大批量MGET若一次查询上百个键,虽然减少了往返,但会阻塞单线程处理其他请求,建议按业务拆分到不同批次。
数值自增与过期时间管理
String类型在存放整型值时,Redis会采用特殊编码节约内存,并允许使用INCR、DECR、INCRBY等命令进行原子算术运算。这些操作在服务端单线程中完成,不需要客户端加锁,非常适合统计页面访问量或生成自增订单号。比如用INCR visit:home就能让计数加一,返回的是计算后的新值;若键不存在则先从零开始。
过期管理方面,除了在SET时指定,还可以用EXPIRE给已有键添加存活时间,用TTL查看剩余秒数。一个常见误区是认为SET覆盖写会继承原过期时间,实际上新写入会清除旧的过期设定。以下代码演示了在Java中通过Jedis客户端操作自增与过期:
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 原子自增并设过期
jedis.incr("order:id");
jedis.expire("order:id", 3600);
// 读取剩余时间
long ttl = jedis.ttl("order:id");
System.out.println("剩余存活秒数:" + ttl);
在限流场景中,常结合INCR与EXPIRE实现每分钟最多十次访问。但上述Java代码分两步执行,极端情况下自增后进程崩溃会导致键永久有效。更稳妥的做法是用Lua脚本保证原子性,或者使用支持SET复合参数的客户端方法一次性完成。对于浮点数,Redis提供INCRBYFLOAT,它返回字符串形式的新值,精度问题需由调用方评估。
追加修改与二进制安全特性
除了整体覆盖,String还支持APPEND命令向原值末尾拼接内容,以及GETRANGE、SETRANGE做局部读写。由于Redis的String是二进制安全的,这意味着它可以保存包含换行、空字符的字节流,不会像C字符串那样遇零截断。因此可以用一个键存放用户上传文件的分片,再用SETRANGE在指定偏移处写入,避免反复读取全量。
下面的例子展示如何用APPEND与GETRANGE处理日志缓存:
SET log:error "" APPEND log:error "db timeoutn" APPEND log:error "rpc failedn" GETRANGE log:error 0 -1
不过APPEND在值已经很大时,可能引发内存重新分配与拷贝,对性能敏感的服务应控制单值体积。一般建议String大小不超过几十KB,更大的数据考虑使用Hash或分片。另一个易混淆点是STRLEN返回的是字节数而非字符数,在存放中文UTF-8文本时,一个汉字占三字节,统计长度时要按业务语义转换。通过合理组合这些命令,开发者能构建出高效的缓存层、计数系统与轻量消息暂存区。