我有一项服务,使用纯 HTTP 以极高的速率向最终用户提供图像。图像大小在 4 到 64kbytes 之间,总共有 1.300.000.000 张。数据集大小约为 30TiB,更改(新对象、更新、删除)占请求的不到 1%。每秒的请求数从 240 到 9000 不等,并且几乎分散在各处,只有少数对象特别“热门”。
到目前为止,这些映像是 ext3 文件系统上的文件,分布在大量中型服务器上,并且只读。这带来了几个问题:
- 使用文件系统效率很低,因为元数据很大,inode/dentry 缓存在 linux 上易失性很强,而且一些守护进程倾向于使用 stat()/readdir() 来遍历目录结构,这在我看来非常昂贵。
- 更新数据集非常耗时,并且需要在 A 集和 B 集之间重新安装。
- 唯一合理的处理是在块设备上运行备份,复制等操作。
我想要的是一个守护进程:
- 使用 HTTP(获取、放置、删除以及更新)
- 以高效的结构存储数据。
- 索引应该保留在内存中,并且考虑到对象的数量,开销必须很小。
- 该软件应该能够处理大量连接,并且需要较慢的(如果有的话)时间来加速。
- 启动时应将索引读取到内存中。
- 统计数据很好,但不是强制性的。
我已经对 riak、redis、mongodb、kyoto 和 varnish 进行了一些具有持久性存储的实验,但我还没有机会深入研究。
答案1
没有什么神奇的解决方案可以满足您的需求。noSQL 数据库实际上不会有所帮助;您需要对您的应用程序架构做出一些基本决策。
有些守护进程倾向于使用 stat()/readdir() 来遍历目录结构
将数据移至任何类型的数据库都无济于事,除非这些守护进程一开始就不应该读取数据。重新配置或关闭它们不是更简单吗?
如果您对您的应用程序一无所知(不,这并不是要求详细说明需求),那么混合方法可能是最佳选择 - 将元数据保存在数据库中,而将内容本身保存在文件系统中(并且有一些非常具体的原因可以说明为什么关系数据库可能比 NoSQL db 更合适)。如果是我,我也会考虑分发存储,而不仅仅是复制它。
索引应该保留在内存中
如果您有 13 亿条记录,每条记录都有 300 字节的元数据,则需要大约 6Gb 的内存。其中大部分永远不会被访问,但这会阻止内存用于内容缓存。
Linux 上的 inode/dentry 缓存不稳定
您是否尝试过调整它?