Write-through缓存 Redis

6

我一直在思考如何可靠地实现写入穿透缓存机制来存储实时数据。

基本上我们需要的是这个:

Save data to Redis -> Save to database (underlying)  
Read data from Redis <- Read from database in case unavailable in cache  

在线资源在实施此缓存策略方面似乎很少。

问题是:

1)Redis和数据库(在我这种情况下为Mongo)之间没有内置事务的可能性。
2)没有事务意味着对基础数据库的写入不可靠。

我认为最直接的实现方式是使用类似Kafka的代理,并将消息放入持久队列中以供稍后处理。
因此,Kafka将成为可靠处理的负责实体。

另一种方式是通过在调度程序中具有自定义实现来检查Redis数据库中的脏记录。初步思考似乎存在一些权衡取舍,如果可能的话,我不想走这条路。

我正在寻找其他实施此方法的选项。
或者是否实际上这是最可行的方法。


2
为什么不先写入数据库?通常的做法是先写入数据库,然后当您从中读取时->创建缓存,当删除/更新实体时->在此键上使缓存无效。因为您会获得更多的读操作而不是写操作。您是否使用带有AOF的Redis?不认为它比Mongo更快写入。 - ipave
@ipave,如果他需要的数据一致性水平取决于先写入数据库还是先进行验证。 - Alexander Petrov
@ipave 对我来说这不起作用。因为我正在处理实时数据,每次请求都需要从数据库中检索以填充缓存,这将消除使用缓存的优势。 - html_programmer
@Alexandar Petrov,我在谈论新记录(尚未创建缓存)。如果您编辑或删除记录,则最好先删除缓存,然后再删除记录。因为如果您删除缓存并且进程死亡-最坏的情况是您需要从数据库中重新读取,这比您删除记录但未删除缓存要好。这样可以避免出现不一致的状态。 - ipave
2个回答

1

比起你之前提到的方法,更好的做法是使用kafka和consumer将数据存储到mongo中。但要了解交付保证,我记得在kafka streams中只有确切一次的保证(在两个主题之间),在你的情况下,你的数据库应该是幂等的,因为你至少获得了一次保证。不要忘记打开Redis的AOF,以免丢失数据。并且不要忘记,在这种情况下,你会得到数据库的最终一致性,带来所有的后果。


谢谢你的建议。难道没有其他方法吗?除了理论读物,我找不到任何关于写通实现的好资源。另一件事是,在这种情况下,我的消费者仍然需要一些自定义代码来管理数据库中的写入失败。 - html_programmer
如果你在MongoDB中有一些限制,那么会变成噩梦……所以我不建议这样做。最好只有一个数据库或者先写入数据库再从缓存中读取…… - ipave
是的,但正如我所解释的那样,我无法在保存到数据库后从缓存中读取。这是关于需要随时在缓存中就绪和最新的实时数据。我不会为每个客户端请求的检查和填充缓存而进行数据库请求。我想要分布式缓存的原因是,数据将呈指数级增长(每个谷歌地点都将添加实时提要),并且使用标准数据库通常会导致随着时间的推移性能下降。这就是为什么对我来说将缓存用作主要缓存,并避免未来的头痛是有意义的。 - html_programmer
然后使用这种方法与kafka一起使用,但要准备好由于约束条件引起的错误,因为在检查约束条件之前,您无法确定数据是否正确。并且您将在未经检查的数据下进行计算。因此,据我所知,您有两个选择:1)快速机制可能会出现错误2)慢速机制没有错误。如果您的系统允许出现错误,请选择第一种方式。 - ipave
2pc的速度比这两种方法都要慢得多。并且没有什么魔法可以解决通常的CAP定理问题(在两个存储中都有两个状态)。我从未见过Redis中有这种机制。你必须自己实现它。 - ipave
显示剩余3条评论

0

经过评估,我将使用MongoDB作为单个数据存储,而不使用Redis。
过早的优化可能会有害。

无论如何,在基准测试之后我可以添加额外的架构。
重构成缓存的计划应该不会太难。

扩展是一个额外的问题,所以我现在不应该在开发过程中被打扰。

接受@Ipave的回答,暂时采用单一数据存储。


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