使用Hazelcast/Redis作为数据库支持的缓存需求

3
我正在开发一个分布式Java应用程序,需要在每个请求上检查一组黑名单用户ID。
如果请求失败了某些资格规则,则系统应将用户ID(请求参数)添加到黑名单中。我正试图找到合适的缓存解决方案来实现黑名单。
我的要求是:
- 查询黑名单速度应非常快 - 黑名单持久性技术应具有可伸缩性 - 所有黑名单数据也应该在RDBMS上持续存在,以备故障转移/重新加载等情况。
有两个可能的解决方案:
选项1:可以使用redis存储黑名单数据。每当请求不符合资格规则时,我可以轻松地将userid添加到redis缓存中。
- 优点:查询速度极快,易于实现 - 缺点:尽管它能运行,但信任redis持久性,因为它是按设计而非一种持久层的缓存解决方案。
选项2:可以同时使用redis存储黑名单数据,同时在RDBMS上维护db表格以用于黑名单。每当请求不符合资格规则时,我可以同时将userid添加到redis缓存和rdbms表格中。
- 优点:查询速度极快,有从数据库重新加载redis缓存的能力(可能) - 缺点:redis和数据库之间存在一致性问题。
选项3:可以使用Hazelcast作为Hibernate L2缓存。当我将任何用户ID添加到黑名单中时,它会同时添加到缓存和数据库中。
对于选项3,我有几个问题:
- Hazelcast L2缓存是否适合保留此类黑名单用户列表? - Hibernate是否管理缓存与数据库之间的一致性问题? - 应用程序重新启动时,如何重新加载L2缓存?
还有一个问题:
- 您对这样的用例有其他建议吗?
编辑:
- 黑名单中将有100m条记录,我有几个类似的黑名单。 - 我的读取性能很重要。我需要在黑名单中查询键的存在性约为100ms

你的“查询”会是什么样子?我期望黑名单主要是基于纯键访问的(例如基于用户名或用户ID)。你能澄清一下吗? - noctarius
3个回答

4

Ygok,

我还在等待查询需求的澄清,但我可以假设它是通过键进行查找(因为您提到了Redis,而Redis没有查询语言。Hazelcast确实有Distributed Query / Predicate API)。使用Hazelcast进行键查找是一种非常快速的操作。

选项2中,您需要在RDBMS和Redis缓存之间维护数据一致性。使用Hazelcast MapLoader / MapStore,您可以实现write-through- / read-through-缓存概念。您只需要将条目放入缓存中,Hazelcast会立即或按配置延迟(批处理)将其持久化到RDBMS中。

就性能而言,请随意熟悉最近的Hazelcast / Redis benchmark

如果您有任何问题,请告诉我。


2

我之前也有类似的问题,首先,你要存储多少数据,需要花费多少内存?每秒需要查询多快?数据结构是什么样子的,只有userId作为键吗?

  • Hazelcast在我的测试中查询速度不是很快(您可以自己尝试),但它可以存储大量内存数据。Hazelcast使用Java默认序列化,它会消耗大量的内存和IO。

  • Hazelcast提供Hibernate L2缓存,缓存数据存储在Hazelcast上(仅查询缓存),因此重新启动应用程序不会影响缓存。

  • Redis提供内存数据持久性(DUMP和AOF),当服务器崩溃时可能会丢失一些数据,但它非常快。

  • 如果您不想丢失任何数据,请存储在多个MySQL服务器上(通过userId将数据拆分到不同的服务器上,但您应该考虑添加新服务器时可能出现的问题),同时,您可以添加本地缓存(例如Ehcache或google CacheBuilder)并设置过期时间,这可以提高性能。


如果您的键长度为10个字节,100000000 * 10个字节几乎需要1GB内存,那么您可以选择Redis(Master/Slave with sentinel mode),并使用dump persistent模式。如果需要进行其他用途的存储,必须存储在RDBMS上。如果只考虑数据丢失,可以通过脚本将Redis dump文件备份到NAS。 - Derek J.

1

使用Redisson框架,可以实现Redis缓存和RDBMS之间的一致性。它为Map对象提供了write-throughread-through策略,需要在您的情况下使用MapWriterMapLoader对象。

请阅读此文档部分


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