本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
【腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
今天我看到群里有人在讨论 Redis,说自从 antirez 首次离开后他们公司很少更新 Redis,Redis 现在更新了啥功能?
实际上,antirez 确实离开过,但后来又回归了。而且现在 Redis 已经发布到了 8.x 版本了,最近的 8.8 还带来了新的数据结构数组(Arrays),以及 8.0 版本重新采用了 AGPLv3 开源许可证。
最新的 Redis 8.10 也已正式发布,主打一次导入省 11% 时间,1000 万个 key 省 300MB 内存,超级实用。同时对于 Java 开发者来说,更好的消息是 Lettuce 7.7.0 已经同步支持了全部新命令,升级后可以立刻用上。
下面我们一起来看看 Redis 省内存的秘诀吧!
Redis 开始省内存了
可能是今年以来内存价格涨的太离谱了,Redis 开始省内存了。
8.10 带来的 Compact Hashes + HIMPORT 成了 hash 内存大户的救星。
解决什么问题?
在 Redis 的典型业务场景中,有一种非常常见的内存浪费。大量 key 拥有完全相同的 field 名称集合。比如缓存用户对象:
HSET user:1 name alice email a@example.com age 30
HSET user:2 name bob email b@example.com age 25
HSET user:3 name carol email c@example.com age 28
每一条记录里,name、email、age 这三个字段名都被重复存储了一遍。假设有 1000 万用户,每个字段名平均 10 字节,仅字段名就要多占用约 300MB。这是 Redis hash 结构长期存在的“硬伤”,field 名和 value 绑定存储,无法跨 key 复用。
Compact Hashes
Compact Hashes 给 schema 相同的 key 共享字段名。这就是 Redis 8.10 引入的紧凑哈希(Compact Hashes)编码。
当多个 key 共享同一套字段名(schema)时,Redis 只在内部保存一份字段名副本,所有 key 共享引用。对使用者完全透明,用 HIMPORT 写入的 key 就是普通 hash,HGETALL、HSET、HDEL 等所有现有命令行为不变。
通过下列新增的监控指标可以观察压缩效果。
INFO STATS # 查看 hash_templates、hash_template_keys
INFO MEMORY # 查看 used_memory_hash_templates
MEMORY USAGE user:1 # 统计该 key 自身 + 模板分摊的内存
HIMPORT
HIMPORT 这个命令是为批量导入而生的命令族。
要知道光省内存还不够,导入路径也要配套。HIMPORT 是一个容器命令,采用“会话级 fieldset”设计。
HIMPORT PREPARE <name> field1 field2 ...:声明一次字段名,注册为命名 fieldset(作用域仅限当前连接,其他客户端不可见,连接断开即失效);HIMPORT SET <key> <name> value1 value2 ...:按位置对齐字段名,只传 value 创建 hash;HIMPORT DISCARD <name>/HIMPORT DISCARDALL:清理 fieldset。
HIMPORT PREPARE u name email age
HIMPORT SET user:1 u alice a@example.com 30
HIMPORT SET user:2 u bob b@example.com 25
官方基准测试给出的数据表明:导入 100 万条 3 字段记录,HIMPORT 耗时 10.589 秒,HSET 为 12.029 秒,快约 11%。并且字段越多、字段名越长,省带宽的效果越明显。
文章配图参见我的公众号:https://mp.weixin.qq.com/s/76gk_ZsHCvgKTBbob3YKcQ。
Java 侧怎么用?
Lettuce 7.7.0 已原生支持 HIMPORT,并做了“懒加载 per-connection prepare”,自动处理 fieldset 在连接池中的注册与断线重连后的恢复。
Maven 依赖只需变更版本号即可。
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>7.7.0.RELEASE</version>
</dependency>
同步 API 示例(具体方法签名以 Lettuce 官方文档为准)如下所示。
RedisCommands<String, String> commands = connection.sync();
// 声明 fieldset(Lettuce 会自动在当前连接上懒加载 prepare)
commands.himportPrepare("user-fields", "name", "email", "age");
// 批量导入——只传 values
commands.himportSet("user:1", "user-fields", "alice", "a@example.com", "30");
commands.himportSet("user:2", "user-fields", "bob", "b@example.com", "25");
上面的代码注意事项有两个。
- fieldset 是连接状态。在连接池场景下,Lettuce 已自动处理各连接的 prepare 与重连恢复;但如果你在多条物理连接上混用,要确认每条连接都已注册 fieldset。
- hash 遍历顺序不保证与 PREPARE 声明顺序一致,
HGETALL/HKEYS返回顺序不做保证,代码中不要依赖顺序。
如果大家还在用 Spring Data Redis,官方封装尚未跟进新命令时,可以通过 StringRedisTemplate.execute 拿到原生 Lettuce 连接调用,或直接使用 RedisTemplate 的 executeWithStickyConnection 访问底层 API。
Redis 8.10 还有一些其它新命令或特性,我还在学习研究中,我们下次再表。
今天是教师节,祝天下教师节日快乐!

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » 内存涨价太多,省内存的 Redis 8.10 发布了!