dot Redis 8 来了——而且是开源的

了解更多

如何更高效地使用 Redis (至少 x1000 倍)

最近的 Redis v2.8.9 是其发布历史中“最奇怪的野兽”。与以前的版本不同,此版本仅引入了新的 Redis 功能,而不是缺陷修复。随着我们即将完成 2.8.9 在我们的 Redis Cloud 服务中的推出,我想借此机会简要总结一下这些更新给我们的用户。

HyperLogLog 数据结构

首先是向 Redis 添加了新的 HyperLogLog 数据结构。 HyperLogLog 允许您估计集合的基数,或者换句话说,获得唯一项目的近似计数。 即使在添加 HLL 之前,您也可以使用 Redis 来计算东西,但 HLL 的存在理由是让您使用固定数量的内存和恒定的复杂度来做到这一点。 由于没有免费的午餐,因此权衡是 HLL 的计数具有高达 0.81% 的标准误差。 如果您想了解更多信息,请查看 这篇文章,其中 antirez 提供了对 HyperLogLog 算法的惊人概述以及实现它的一些挑战。 除了 Phillipe Flajolet 的 原始论文 之外,网络上还有 几个 其他 资源 解释 HLL,包括 这个漂亮的视觉效果

让我们看看如何很好地使用 HLL,例如通过向您的应用程序添加一些实时分析。 假设您想跟踪一天中每小时有多少唯一用户正在使用您的应用程序。 在 HyperLogLog 之前,您可以在 Redis 中执行此操作的一种简单方法是将用户的 ID(例如,他们的电子邮件)存储在每小时的集合中,因此对于每个请求,您都会执行类似的操作

SADD users:<date>:<hour> <email>

这样,任何此类集合的 SCARD 的结果将是该小时的唯一用户数。 这种方法的问题在于它会消耗大量内存。 如果您的应用程序平均每小时看到 50K 用户,并且假设每个标识符平均为 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 – 它可以让你计数(并且 我喜欢计数!),但这基本上就是全部。 当然,你想要在 #IoT 中计算很多不同的东西,但这就是它所能达到的最令人兴奋的事情。 另一方面,在集合中按字典顺序对成员进行排名可以开启一个充满可能性的世界,就像许多其他 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,只需创建一个新数据库。 问题? 反馈? 电子邮件推文 我 – 我非常容易联系 🙂