中等到大型值的键值存储

16
我们有一个系统,存储着数百万幅图片,大小不等,从8KB到500KB不等,中值约为15KB,平均为30KB。总数据集目前约为100GB。我们想要通过图像的哈希值来访问该图像(这可以更改,但需要能够有效地从图像计算出来,以检查图像是否已在数据存储中 - 处理图像使得两个图像在像素级别上完全相同 IFF它们在字节级别上完全相同)。持久性是很重要的。
目前,我们将它们全部存储为目录中的文件 - 目录列表由内核缓存,并根据需要执行实际文件读取。据我所知,键值存储的主要优点(相对于使用文件系统作为其中之一)是读取较小的值,因为整个页面可以被缓存,而不仅仅是单个值。所有访问都来自与数据相同的Web服务器(位于内部网络上),尽管我们可能会移动到检查密钥是否存在于远程机器上(大多通过10GbE连接)。
虽然没有特定的原因要更改它,但随着系统的其他主要部分的更改,重新考虑当前方法似乎是值得的。
鉴于工作负载的读取主要是按插入顺序和随机(尽管很可能是重复的)访问任意键,除频繁写入(大约1:10写入:读取的数量级)之外,从文件系统转换到键值存储是否有很大优势?

这取决于您当前的系统。如果它是单块式的(单台机器从单个存储位置提供服务),通过添加多个节点并将数据副本存储在更接近消费该数据的客户端处,您可能会看到一些好处。为了回答这个问题,您需要详细说明当前系统的组成以及需要纠正的当前瓶颈所在。 - GalacticJello
2KB文件与10MB文件在元数据开销/目录开销方面完全不同。从磁盘读取2KB文件更容易受到元数据限制和寻址限制,而10MB文件的主要时间是实际流式传输。您能否多说一些有关文件大小分布的情况?小文件是常态还是中等文件? - dmeister
请查看微软Sharepoint,它可能满足您的需求。在这种情况下,没有必要重新发明轮子。 - Alex
4个回答

15
总结:对于您的数据完整性、持久性、大小和速度的要求,我推荐使用Redis。可以在此处查看一个不错的介绍演示:
https://simonwillison.net/static/2010/redis-tutorial/ n.b. 更多信息会更有帮助,但基于您提供的信息和我的了解,以下是一些主要参与者: Memcached:
https://memcached.org/
一个免费、开源、高性能、分布式内存对象缓存系统,适用于加速动态 Web 应用程序。
+ 适用于 Web 应用程序、免费、开源。
- 如果服务器崩溃(memcached 进程失败或系统重启),所有会话都将丢失。在更高级别(商业用途)上存在性能限制。 Redis:
https://redis.io/
类似于 memcached,但具有数据持久性,支持多个值类型、带原子增量/减量的计数器和内置键过期。
+ 将数据保存到磁盘上,因此永远不会丢失;非常简单、快速、灵活(键可以包含字符串、哈希、列表、集合和排序集合)、分片、由 VMware 维护而不是个人。
- 有限的集群化。
LevelDB: https://google-opensource.blogspot.com/2011/07/leveldb-fast-persistent-key-value-store.html 这是一种快速的键值存储引擎,由谷歌编写,可以将字符串键映射到字符串值。 + 谷歌支持。 - 可能需要使用谷歌 + ;)
TokyoCabinet: https://fallabs.com/tokyocabinet/ 它包括锁定、ACID事务和二进制数组数据类型的支持。 + 速度和效率高。 - 在某些地区(例如美国)不太知名。
Project Voldemort: https://project-voldemort.com/ 这是一个高级的键值存储,用Java编写。提供多版本并发控制(MVCC)以进行更新。副本的更新是异步完成的,因此不能保证数据一致性。 + 功能丰富。 - 一致性较差。

MongoDB:
https://www.mongodb.org/
MongoDB是一个可扩展、高性能、开源的面向文档型数据库,用C++编写。具有复制和高可用性功能,可以在局域网和广域网上进行镜像复制和自动分片。在Ruby on Rails社区中很受欢迎。
+ 安装简便,文档齐全,提供支持。
- 相对较新。

Couch:
http://www.couchdb.org/
与Mongo类似,旨在处理文档数据库。
+ 复制、高级查询。
- 集群、磁盘空间管理。

Cassandra:
https://cassandra.apache.org/
Apache Cassandra是一个容错和去中心化的数据库,被Netflix、Twitter和Reddit等公司使用。
+ 集群和复制。
- 需要更多的设置知识。

由于时间不足,我无法提供所有参考资料,但希望这至少有所帮助。


11

根据以下因素:

  • 文件数量
  • 文件在文件系统上的结构
  • 使用的文件系统类型
  • 使用的存储类型

你可能会遇到inode耗尽的问题,或者访问文件时速度变慢(例如,如果你在单个目录中放置了太多条目)。

在访问文件(和/或创建目录)时,你还需要注意以原子方式进行操作,而KV存储通常会为你处理这些。

过去,我曾经在fs-as-key-value-store方法中遇到过所有这些问题 :)。

但是,它是可以完成的,例如Bigdis,这是redis作者本人实现的基于磁盘文件的redis KV协议,但你必须对操作非常小心。

根据你的问题,你可能会发现MogileFS或直接使用云端S3是更好的解决方案。


2
您提供的信息太少,无法给出具体答案,因此只能针对您所描述的一些方面进行回答:
- 数据完整性 这可以是任何内容 - 例如,应禁止非授权数据更改和/或至少应检测到任何此类事件... 或者它可以仅涉及“RAID和/或备份...”。
- “相同的图像” 图像文件包含多个元数据字段/区域... 如果一个图像具有元数据而另一个没有(或某些元数据字段不同),则您的方法会将两个像素完全相同的图像视为不同... 这是您想要的吗? 在此领域的另一个方面是文件格式(PNG与BMP与JPEG等)和压缩... 相同的图像和不同的格式和/或压缩算法(甚至包括无损的ZIP与LZW,JPEG等更糟糕)可能会导致将相同的图像分类为不同的... 这是您想要的吗?
- “数十万张图像”和“2 KB - 10 MB” 这并不能说明太多... 比如说中位数与平均值图像/文件大小是多少?
- 访问 对这些文件/图像的访问是否分布式(例如CDN)?还是基于局域网?
对于您所描述的问题,还有其他几十个相关方面...
如果没有进一步的具体信息,我认为任何统计数据/基准测试/建议都只能是最好的幸运尝试。
可能的解决方案包括分布式系统(可以基于文件系统/内存/数据库)和/或基于SSD和/或RAID和/或SAN等存储。
您感兴趣的“KeyValueStore”点可能会有关联,但在我遇到处理这么多图像的大多数情况下,这种存储并不会增加任何独特的功能(在某些情况下甚至会有所损害)。

数据完整性确实太过模糊,我必须承认:我唯一关心的是从键值存储中获取的数据与输入的数据相同。问题中提到了相同的图像(它们被处理成像素完全相同或字节完全相同)。否则,现在问题已经解决了其余部分。 - gsnedders
@gsnedders 感谢您提供的额外信息...即使有数百万张图片,我也不明白KeyValueStore会带来什么好处...您具体期望KeyValueStore能做些什么? - Yahia

1
如果您的数据不到1TB,您可能不需要高可用性的NoSQL数据库,大多数NoSQL数据库要求数据保存在RAM中。我建议使用一个普通的关系型数据库,创建一个以哈希为主键和包含数据的blob的表格。您会惊讶于它的性能表现得有多好,并且您不需要担心inode耗尽的问题。
如果您的数据是文本/可压缩的,则关系型数据库更好。根据我的经验,很少有NoSQL数据库会为您压缩数据,您必须在客户端进行操作。但是MySQL/MariaDB提供透明的压缩功能。
另一个选择是RocksDB。对于某些用例,它非常适合节省磁盘空间,因为它支持使用自定义字典的zstd压缩。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接