我正在尝试在间隔3分钟后缓存Kafka记录,因为它将过期并从缓存中删除。
使用springboot编写的使用kafka消费者获取的每个传入记录都需要先在缓存中进行更新,然后如果存在,我需要丢弃下一个重复记录(如果它与缓存记录匹配)。
我尝试过如下使用咖啡因缓存,
@EnableCaching
public class AppCacheManagerConfig {
@Bean
public CacheManager cacheManager(Ticker ticker) {
CaffeineCache bookCache = buildCache("declineRecords", ticker, 3);
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Collections.singletonList(bookCache));
return cacheManager;
}
private CaffeineCache buildCache(String name, Ticker ticker, int minutesToExpire) {
return new CaffeineCache(name, Caffeine.newBuilder().expireAfterWrite(minutesToExpire, TimeUnit.MINUTES)
.maximumSize(100).ticker(ticker).build());
}
@Bean
public Ticker ticker() {
return Ticker.systemTicker();
}
}
我的卡夫卡消费者如下所示,
@Autowired
CachingServiceImpl cachingService;
@KafkaListener(topics = "#{'${spring.kafka.consumer.topic}'}", concurrency = "#{'${spring.kafka.consumer.concurrentConsumers}'}", errorHandler = "#{'${spring.kafka.consumer.errorHandler}'}")
public void consume(Message<?> message, Acknowledgment acknowledgment,
@Header(KafkaHeaders.RECEIVED_TIMESTAMP) long createTime) {
logger.info("Recieved Message: " + message.getPayload());
try {
boolean approveTopic = false;
boolean duplicateRecord = false;
if (cachingService.isDuplicateCheck(declineRecord)) {
//do something with records
}
else
{
//do something with records
}
cachingService.putInCache(xmlJSONObj, declineRecord, time);
我的缓存服务如下,
@Component
public class CachingServiceImpl {
private static final Logger logger = LoggerFactory.getLogger(CachingServiceImpl.class);
@Autowired
CacheManager cacheManager;
@Cacheable(value = "declineRecords", key = "#declineRecord", sync = true)
public String putInCache(JSONObject xmlJSONObj, String declineRecord, String time) {
logger.info("Record is Cached for 3 minutes interval check", declineRecord);
cacheManager.getCache("declineRecords").put(declineRecord, time);
return declineRecord;
}
public boolean isDuplicateCheck(String declineRecord) {
if (null != cacheManager.getCache("declineRecords").get(declineRecord)) {
return true;
}
return false;
}
}
但是,每当有一条记录进入使用者时,我的缓存始终为空。它没有保存记录。
所做的修改:
在完成建议后,我已经添加了以下配置文件,并且更多的R&D删除了一些较早的逻辑,现在缓存可以按预期工作,但是当所有三个使用者都发送相同的记录时,重复检查失败。
`
@Configuration
public class AppCacheManagerConfig {
public static Cache<String, Object> jsonCache =
Caffeine.newBuilder().expireAfterWrite(3, TimeUnit.MINUTES)
.maximumSize(10000).recordStats().build();
@Bean
public CacheLoader<Object, Object> cacheLoader() {
CacheLoader<Object, Object> cacheLoader = new CacheLoader<Object, Object>() {
@Override
public Object load(Object key) throws Exception {
return null;
}
@Override
public Object reload(Object key, Object oldValue) throws Exception {
return oldValue;
}
};
return cacheLoader;
}
`
现在我将上述缓存用作手动放置和获取。
答案 0 :(得分:1)
我猜您正在尝试为Kafka实施记录重复数据删除。
这是类似的讨论:
https://github.com/spring-projects/spring-kafka/issues/80
这是当前的抽象类,您可以对其进行扩展以实现必要的结果:
您的缓存服务绝对是不正确的:Cacheable
批注允许标记数据获取器和设置器,以通过AOP添加缓存。在代码中,您可以清楚地实现一些自己的低级缓存更新逻辑。
至少下一次可能的更改可能会帮助您:
删除@Cacheable
。您不需要它是因为您手动使用缓存,因此它可能是冲突的根源(尤其是在使用sync = true
时)。如果有帮助,也可以删除@EnableCaching
-它使您支持此处不需要的与缓存相关的Spring注释。
尝试使用适用于其他bean的参数删除Ticker
bean。它不会对您的配置有害,但是通常它仅对测试有用,而无需另外定义。
仔细检查什么是declineRecord
。如果它是序列化的对象,请确保序列化正常进行。
添加recordStats()
进行缓存,并输出stats()
进行日志记录以进行进一步分析。