跳到主要内容

保证缓存一致性

警告

之前,我们已经通过对象缓存关联缓存计算缓存三篇文章详细讲解了Jimmer如何在数据被修改时自动删除受影响的缓存。

所以,这里不再重复讨论Jimmer是如何智能地删除受影响的缓存。

本文讨论的焦点是,Jimmer如何保证已发出的缓存数据删除行为最终一定能成功。

无论是对象缓存关联缓存那种全自动的一致性,还是计算缓存那种需要用户辅助的一致性,Jimmer的缓存一致性都是由触发器驱动的。

Jimmer的触发器分为BinLog触发器和Transaction触发器。

针对不同的情况,Jimmer采用不同的策略来保证缓存一致性,即,保证缓存清理操作必然成功。

BinLog触发器的一致性(推荐)

trigger-typeBINLOG_ONLYBOTH时,Jimmer使用BinLog触发器删除失效缓存。

在这种情况下,开发人员响应消息队列的通知,简单处理后调用Jimmer的BinLog API (这段用户代码很简单,其复杂度可以忽略不计)。用户调用BinLog API会发起所有触发器回调,包括缓存删除。

以Kafka为例,只要保证调用BinLogAPI成功后才提交消费进度,则可以保证缓存清理最终成功。

Transaction触发器的一致性

trigger-typeTRANSACTION_ONLY时,Jimmer会被迫使用Transaction触发器删除失效缓存。

对于Transaction触发器而言:

  • 只有用户在当前App内调用Jimmer API导致的修改才做才会发起触发器回调。

  • 所有触发器回调都在事务提交前完成。

假如采用直接删除缓存的简单实现,只要缓存删除发生异常,就会导致事务被回滚。很明显,这种实现并不合理。

因此,当trigger-typeTRANSACTION_ONLY时,用户认知中的缓存删除操作都会被延迟执行。缓存删除操作先不执行,而是被存入JIMMER_TRANS_CACHE_OPERATOR表。

警告

Jimmer会自动创建``JIMMER_TRANS_CACHE_OPERATOR`表。

然而,默认的org.babyfish.jimmer.sql.dialect.DefaultDialect不支持此操作,会抛出异常。

因此,如果需要用Transaction触发器驱动缓存一致性,就不要使用默认的DefaultDialect,要明确指定数据库方言。

JIMMER_TRANS_CACHE_OPERATOR表的修改和业务表的修改属于同一个数据库本地事务,二者要么都成功,要么都失败。

事务提交成功后,Jimmer会马上执行一次Flush操作。

所谓Flush操作,就是从JIMMER_TRANS_CACHE_OPERATOR表中获取尚未执行的用户认知中的缓存删除操作,执行真正的缓存删除操作,如果成功,删除相关记录。

对于事务提交后立即执行的Flush操作而言:

  • 如果成功自然最好,这时拥有良好的实时性。大部分情况下也应该如此。

  • 即使没有成功也不要紧。因为Jimmer会周期性执行Flush操作保证相关缓存操作最终会成功。

    Flush操作的间隔受全局SpringBoot配置项jimmer.transaction-cache-operator-fixed-delay控制,该配置以毫秒为单位,默认5000