Redis publica y suscríbete.
Publicar y suscribirse: un editor de mensajes publica un mensaje y un suscriptor del mensaje recibe el mensaje . Los dos están conectados a través de algún medio.
Por ejemplo, cuando te suscribes a una revista, se publicará una cada mes. Cuando se libera, el repartidor puede ver el contenido de la revista cuando se la entregan. La revista sólo nos será entregada si nos suscribimos
La publicación y suscripción de Redis (pub/sub) es un modelo de comunicación de mensajes: el remitente (pub) envía mensajes y los suscriptores (sub) reciben mensajes.
Los clientes de Redis pueden suscribirse a cualquier cantidad de canales.
Suscribirse/publicar gráfico de mensajes:
Como puede verse en la figura, lo que se requiere:
- Remitente del mensaje, 2. Canal, 3. Suscriptor del mensaje
mecanismo de publicación-suscripción
- Cuando un cliente
PUBLISH
publica mensajes a los suscriptores a través del comando, el cliente se llama editor.publisher
- Cuando un cliente recibe un mensaje a través
subscribe
de oPSUBSCRIBE
, el cliente se llama suscriptorsubscriber
- Para desacoplar la relación entre editores y suscriptores, Redis utiliza canales
channel(频道)
como intermediarios entre los dos: el editor envía mensajes directamente al canal y el canal es responsable de enviar el mensaje al suscriptor. Entre el editor y el suscriptor No hay contacto directo entre ellos y ninguno de los dos conoce la existencia del otro.
Los suscriptores 1, 2 y 3 se suscriben al canal del canal. Cuando se publica un mensaje en el canal, el mensaje se enviará a los tres clientes suscriptores.
implementación de demostración
Enlace de referencia del estudio
Introducir dependencias
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Agregar archivo de configuración
spring:
redis:
host: 127.0.0.1
database: 5
password:
port: 6379
Crear un contenedor de escucha
@Configuration
public class CatListenerConfig extends CachingConfigurerSupport {
/**
* 消息监听容器
*
* @param factory
* @return
*/
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory factory){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
//订阅一个通道 该处的通道名是发布消息时的名称
container.setConnectionFactory(connectionFactory);
//订阅了一个叫cat 的通道
container.addMessageListener(catAdapter, new PatternTopic("cat"));
container.addMessageListener(fishAdapter, new PatternTopic("fish"));
return container;
}
}
@Component
public class CatListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] bytes) {
System.out.println("我是监听者,我监听到的消息是 " + message.toString());
}
}
package com.maoxs.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 监听发送的消息
*/
public class FishListener implements MessageListener {
@Autowired
RedisTemplate redisTemplate;
@Override
public void onMessage(Message message, byte[] bytes) {
System.out.println("我是Fish监听" + message.toString());
}
}
Crear una clase de prueba y monitorear la versión de prueba
@RestController
public class TestController {
@Resource
StringRedisTemplate stringRedisTemplate;
@PostMapping("/cat")
public void test2(){
stringRedisTemplate.convertAndSend("cat","测试:消息发布者发布消息");
}
@PostMapping("/fish")
public void fish(){
stringRedisTemplate.convertAndSend("fish","测试:消息发布者发布消息");
}
}
Resultados de la prueba
-
Modo adaptador
2.1 Configuración
/** * MessageListenerAdapter 模式 * 该处topic的 key为bean的name * @param connectionFactory * @param adapterMap * @return */ @Bean public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,Map<String, MessageListenerAdapter> adapterMap) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); adapterMap.keySet().forEach(topic-> container.addMessageListener(adapterMap.get(topic),new PatternTopic(topic))); return container; }
Monitor 1
package com.sst.loan.risk.listener; import com.sst.loan.risk.manager.RuleLoadManager; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 监听适配器 * * @author 蔡定努 * @date 2023/06/13 10:26 */ @Slf4j @Component("ruleRefreshAdapter") public class RuleRefreshAdapter extends MessageListenerAdapter { @Override public void onMessage(Message message, byte[] bytes) { log.info(">>>>>>> 消息适配器收到刷新规则的请求 <<<<<<<<<<<<<<"); } }
monitor 2
package com.sst.loan.risk.listener; import com.sst.loan.risk.manager.RuleLoadManager; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 监听适配器 * * @author 蔡定努 * @date 2023/06/13 10:26 */ @Slf4j @Component("ruleRefreshAdapter2") public class RuleRefreshAdapter2 extends MessageListenerAdapter { @Override public void onMessage(Message message, byte[] bytes) { log.info(">>>>>>> 消息适配器收到刷新规则的请求 <<<<<<<<<<<<<<"); } }
prueba
@Resource private StringRedisTemplate stringRedisTemplate; /** * * @author 蔡定努 */ @GetMapping("refresh") public Object refresh() { stringRedisTemplate.convertAndSend("ruleRefreshAdapter","refresh"); return Result.success(); } /** * * @author 蔡定努 */ @GetMapping("refresh") public Object refresh() { stringRedisTemplate.convertAndSend("ruleRefreshAdapter2","refresh"); return Result.success(); }