[英]How to broadcast cache invalidate messages to all servers running a web app?
I have a Java based web app hosted on AWS.我有一个基于 Java 的 Web 应用程序托管在 AWS 上。 It is read-mostly so it makes a lot of sense to cache objects retrieved from the database for performance.
它以读取为主,因此缓存从数据库中检索的对象以提高性能非常有意义。
When I do update an object, I would like to be able to broadcast to all the servers that the object was saved and it should be invalidated from all local caches.当我更新一个对象时,我希望能够向所有服务器广播该对象已保存并且应该从所有本地缓存中使其无效。
The does not need to be real time.不需要是实时的。 Stale objects are annoying and need to be flushed within about 20 seconds.
陈旧的对象很烦人,需要在大约 20 秒内刷新。 Users notice if they stick around for minutes.
用户会注意到他们是否停留了几分钟。 Cache invalidation does not have to happen the millisecond that objects get saved.
缓存失效不必在对象保存的毫秒内发生。
Two options come to mind. 我想到了两种选择。 The first is to use Amazon SNS , which can use SQS as a delivery backend.
第一种是使用Amazon SNS ,它可以使用SQS作为交付后端。 This might be overkill, though, since it's designed as a frontend to lots of delivery types, including e-mail and SMS.
然而,这可能是过度的,因为它被设计为许多交付类型的前端,包括电子邮件和SMS。
The approach I'd try is something along the lines of Comet-style push notifications. 我尝试的方法与Comet风格的推送通知类似。 Have each machine with a cache open a long-lived TCP connection to the server who's responsible for handling updates, and send a compact "invalidate" message from that server to everyone who's listening.
让每台带有缓存的计算机打开与负责处理更新的服务器的长期TCP连接,并将该服务器的紧凑“无效”消息发送给正在收听的每个人。 As a special-purpose protocol, this could be done with minimal overhead, perhaps just by sending the object ID (and class if necessary).
作为一种特殊用途的协议,这可以通过最小的开销来完成,也许只需要发送对象ID(如果需要的话,可以发送类)。
Redis is handy solution for broadcasting a message to all subscribers on a topic. Redis是一个方便的解决方案,用于向所有订阅者广播一个主题的消息。 It is convenient because it can be used as a docker container for rapid prototyping, but is also offered by AWS as a managed service for multi-node clusters.
它很方便,因为它可以用作快速原型制作的 docker 容器,但也由 AWS 作为多节点集群的托管服务提供。
Setting up a ReactiveRedisOperations bean:设置ReactiveRedisOperations bean:
@Bean
public ReactiveRedisOperations<String, Notification> notificationTemplate(LettuceConnectionFactory lettuceConnectionFactory){
RedisSerializer<Notification> valueSerializer = new Jackson2JsonRedisSerializer<>(Notification.class);
RedisSerializationContext<String, Notification> serializationContext = RedisSerializationContext.<String, Notification>newSerializationContext(RedisSerializer.string())
.value(valueSerializer)
.build();
return new ReactiveRedisTemplate<>(lettuceConnectionFactory, serializationContext);
}
Subscribing on a topic:订阅主题:
@Autowired
private ReactiveRedisOperations<String, Notification> reactiveRedisTemplate;
@Value("${example.topic}")
private String topic;
@PostConstruct
private void init() {
this.reactiveRedisTemplate
.listenTo(ChannelTopic.of(topic))
.map(ReactiveSubscription.Message::getMessage)
.subscribe(this::processNotification);
}
Publishing a message on a topic:发布关于某个主题的消息:
@Autowired
private ReactiveRedisOperations<String, Notification> redisTemplate;
@Value("${example.topic}")
private String topic;
public void publish(Notification notification) {
this.redisTemplate.convertAndSend(topic, notification).subscribe();
}
RedisInsight is a GUI that can be used for interacting with redis. RedisInsight是一个可用于与 Redis 交互的 GUI。
Here is a complete sample implementation using spring-data-redis. 这是使用 spring-data-redis 的完整示例实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.