最新的 Redis v2.8.9 版本是其发布历史中的“最奇怪的野兽”。与以前的版本不同,此版本仅引入了新的 Redis 功能,而没有缺陷修复。由于我们在 Redis Cloud 服务中即将完成 2.8.9 的推出,我想借此机会为我们的用户简要概括一下这些更新。
首先是向 Redis 中添加新的 HyperLogLog 数据结构。借助 HyperLogLog,您可以估算集合基数,或换句话说,获取唯一项的近似数量。即使在添加 HLL 之前,也可以使用 Redis 来统计内容,但 HLL 的存在理由是让您能够通过固定数量的内存和不变的复杂度进行统计。免费午餐是不存在的,权衡利弊的是 HLL 的计数标准误差高达 0.81%。如果您想了解更多信息,请查看 这篇文章,其中 antirez 对 HyperLogLog 算法以及实施它时遇到的部分挑战提供了精彩的概述。除了 Phillipe Flajolet 的 原始论文 之外,网络上还有 几篇 其他 资源,解释 HLL,包括 这个漂亮的可视化演示。
让我们看看如何将 HLL 付诸实践,例如为您的应用程序添加一些实时分析。假设您想跟踪一整天中每小时有多少个唯一用户在使用您的应用。在出现 HyperLogLog 之前,您可以在 Redis 中通过将用户 ID(例如其电子邮件)存储在每小时集合中,以简单的方式来实现,因此对于每个请求,您会执行类似以下操作:
SADD users:<date>:<hour> <email>
这样,任何此类集合的 SCARD 结果都将是该小时唯一用户的数量。这种方法的问题在于它可能会消耗大量内存。如果您的应用程序平均每小时看到 50,000 个用户,并且假设每个标识符平均为 25 字节,那么任何每小时集合的平均大小大约为 12MB。HLL 仅使用 12KB 即可让您执行相同的操作,因此可以说它高效了三个数量级 😛
在使用 HLL 时,我们会通过以下方式统计用户:
PFADD users:<date>:<hour> <email>
并使用 PFCOUNT 来获得每小时计数。但如果你想(而你通常需要)拥有不同时间段的集合体,如 3 小时、6 小时、12 小时和 24 小时,该怎么办呢?采用 SADD/SCARD 方法,你将需要为每个分辨率再分配几个计数器集合或执行按需/定期 SUNION,这需要耗费 RAM 和 CPU。如上所示,你可以通过使用 HLL 大幅节省,但它实际上还有另一个很大的节省。由于可以非常有效地合并 HLL,因此你无需为每个时间分辨率保存一个计数器,而只需 PFMERGE 相关计数器即可获得总和。
其次,有序集合的字典序。当有序集合的成员得分相同,ZRANGEBYLEX 命令将使用字典排序返回请求的成员范围。与包含 ALPHA 选项的现有 SORT 命令相比,新的字典命令不仅性能更佳,而且允许直接实现 类自动补全 功能(尽管从 RAM 的角度而言,这样的有序集合更昂贵)。
尽管 Flajolet 的发明非常巧妙,并且付出了很多努力才将其纳入 Redis,但我还是更喜欢字典序(不仅是因为它的发音方式)。我之所以有这种偏见,有两个原因,而且两个原因都完全主观。首先,这个 和 那个 Redis 邮件列表的主题揭开了该功能背后的故事。除了在这些通信中提供所有多汁的技术细节之外,它们还出色地展示了团队合作如何在开源项目的制作中发挥作用——Redis 伟大社区的一个杰出范例。最重要的是,它更实用,并且呼吁人们使用它。
我的意思是,想想 HLL——它让你可以计数(而且 我喜欢计数!),但基本上就是这样了。当然,你想要在物联网中计数很多不同的东西,但这就是它能做到的最令人兴奋的事情了。另一方面,对集合中的成员进行字典序排列的能力开启了一个可能的世界,就像许多其他 Redis 命令一样。这里有一个简洁的用法——想象你有一组电子邮件地址,你需要找到某个域中的所有地址。通过编制索引(即 ZADDing)每个地址的反向版本,这将变成一个 ZRANGEBYLEX 的问题。你可以使用以下 Lua 来编制电子邮件地址的索引
redis.call("zadd", KEYS[1], 1, ARGV[1]:reverse())
以及用于在某个域中搜索地址的 Lua 脚本
local res = redis.call("zrangebylex", KEYS[1], "\[" .. ARGV[1]:reverse(), "\[" .. ARGV[1]:reverse() .. "\\xff")
for k, v in pairs(res) do
res[k] = v:reverse()
end
return res
十分期待看到这些新功能还有什么新颖的用途。要立即使用 Redis Cloud 中的 Redis v2.8.9,只要创建一个新数据库即可。有任何问题或反馈?发送电子邮件或发推文联系我 – 我随时可用 🙂