216

Redis中存储亿级键值对

 5 years ago
source link: http://www.apexyun.com/untitled-17/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

迁移系统时,有时你必须建立一个小脚手架。我们最近不得不这样做:在Instagram上,于遗留原因,我们需要将大约3亿张照片映射到创建它们的用户的ID,以便了解要查询的分片(请参阅有关 我们的 更多信息) 分片设置 )。虽然所有客户端和API应用程序都已更新并向我们返回 完整信息,但仍有许多人缓存的旧数据。我们需要一个解决方案:

1. 查找键并快速返回值

2. 将数据存在内存中,理想情况下是在EC2高内存类型(17GB或34GB,而不是68GB实例类型)中

3. 兼容我们现有的基础结构

4. 持久化,以便在服务器宕机时我们不必重跑

这个问题的一个简单解决方案是将它们简单地存储在数据库行中,其中包含“Media ID”和“User ID”列。但是,考虑到这些ID从未更新(仅插入),SQL数据库似乎是多余的。不需要事务,也和其他表没有任何关系。

相反,我们转向 Redis ,一个我们在Instagram上广泛使用的键值存储。Redis是一把key-value的瑞士军刀; 而不是像Memcached那样普通的“Set key,get key”机制,它提供了强大的聚合类型,如有序集合和列表。它具有可配置的持久化模型,其中后台以指定的时间间隔保存,并且可以设置主从同步。我们所有的Redis都在主从服务器上运行,从服务器设置为每分钟保存到磁盘。

首先,我们决定以最简单的方式使用Redis:对于每个ID,key将是媒体ID,值将是用户ID:

SET media:1155315 939

GET media:1155315

> 939

然而,在对此解决方案进行模型设计时,我们发现Redis需要大约70 MB才存储1,000,000个key。根据我们需要的300,000,000,大约要21GB的数据,已经比亚马逊EC2上的17GB实例类型更大。

我们向Redis的核心开发人员之一,乐于助人的 Pieter Noordhuis 提出了意见,他建议我们使用Redis哈希。Redis中的哈希是字典,可以非常有效地编码在内存中; Redis设置'hash-zipmap-max-entries'配置散列可以有效编码的最大条目数。我们发现这个设置最好在1000左右; 任何更高的配置HSET命令都会引起很明显的CPU使用。有关更多详细信息,你可以 查看zipmap源文件

为了用散列类型,我们将所有媒体ID分配到1000个桶中(我们只取ID,除以1000并丢弃剩余部分)。这决定了属于哪个键,接下来在该键的散列中,Media ID是散列中的查找键,用户ID是值。一个例子,给定媒体ID为1155315,它属于桶1155(1155315/1000 = 1155):

HSET "mediabucket:1155" "1155315" "939"

HGET "mediabucket:1155" "1155315"

> "939"

内存差异非常惊人; 使用我们的1,000,000个key(编码为1000个哈希,每个1000个子key),Redis只需要16MB存储。扩展到3亿个key,总数不到5GB,事实上,它甚至适合亚马逊上更便宜的m1.large实例类型,大约是我们原本需要的更大实例成本的1/3。最重要的是,散列中的查找仍然是O(1),非常快。

如果你对尝试这些感兴趣,我们用于运行这些测试的脚本 可以作为GitHub上的Gist (我们在脚本中有Memcached用于比较, 百万个key需要大约52MB)。

点击英文原文链接

更多文章欢迎访问: http://www.apexyun.com

公众号:银河系1号

联系邮箱:[email protected]

(未经同意,请勿转载)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK