Ruby 确保在提交后挂钩中缓存数据时的一致性
对于特定的数据库表,我们需要始终与数据库同步的该数据的内存缓存。我当前的尝试是在提交后将更改写入到缓存中的Ruby 确保在提交后挂钩中缓存数据时的一致性,ruby,activerecord,concurrency,thread-safety,Ruby,Activerecord,Concurrency,Thread Safety,对于特定的数据库表,我们需要始终与数据库同步的该数据的内存缓存。我当前的尝试是在提交后将更改写入到缓存中的钩子中-这样我们可以确保不会写入任何可能稍后恢复的更改到缓存中 但是,此策略易受以下情况的影响: 线程A锁定并更新记录,存储值1 线程A提交更改 线程B锁定并更新记录,存储值2 线程B提交更改 线程B在提交后运行钩子,因此缓存现在有值2 线程A在提交后运行钩子,因此缓存现在有值1,但应该有值2 我对这个问题的看法正确吗?我们如何解决这个问题?你对这个问题的看法是正确的 保存后有一个回调,在同
钩子中-这样我们可以确保不会写入任何可能稍后恢复的更改到缓存中
但是,此策略易受以下情况的影响:
线程A锁定并更新记录,存储值1
线程A提交更改
线程B锁定并更新记录,存储值2
线程B提交更改
线程B在提交后运行钩子,因此缓存现在有值2
线程A在提交后运行钩子,因此缓存现在有值1
,但应该有值2
我对这个问题的看法正确吗?我们如何解决这个问题?你对这个问题的看法是正确的
保存后有一个回调,在同一事务中运行。您可能希望使用该钩子,而不是在事务之后运行的after\u commit
钩子
但是,您需要自己处理回滚事务
或者,您可能希望以不依赖于特定实例的方式编写缓存方法。而是通过首先从数据库重新加载记录来缓存在数据库中找到的最新版本
但即便如此:多线程系统也很难保持同步。您甚至无法确保发送到缓存的第一个或第二个更新是否会被存储,因为缓存系统也可能是多线程的
您可能想了解。我们提出的解决方案是在提交之前锁定缓存以进行读/写,并在提交之后在中解锁它。这似乎很管用。感谢您的见解。由于缓存涉及一个完整的树结构,因此在那里处理回滚实际上也意味着为缓存重新实现类似于db的事务处理。只是使缓存失效并稍后重新加载它也是一个解决方案,但对于树结构来说非常复杂。这类问题没有解决办法吗?记录多久更改一次?你多久看一次记录?缓存中的结构有多复杂?也许可以优化您的数据库模式以进行读取,而不是依赖缓存进行读取?记录可能会经常更改,并且是一个由50-100k条记录组成的树结构,因此我认为在没有缓存的情况下读取(每个请求)不是一个选项。该查询是一个嵌套查询,大约需要1.4秒,我看不出有多大的优化潜力。