SpringBoot+Redis-Stream实现简单消息队列

Redis5.0 中增加了一个数据类型Stream,它借鉴了Kafka的设计,是一个新的强大的支持多播的可持久化的消息队列。

老规矩直接上代码:

一、添加依赖

首先必须得有redis依赖,SpringBoot项目直接添加下面依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

二、Redis相关配置类

Redis配置:

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

}

二、消费者

//消费者
@Component
public class RedisConsumer implements StreamListener<String, MapRecord<String,String,String>> {
    //队列名称
    public final String streamName      = "emailStream";
    //组名称
    public final String groupName       = "emailGroup";
    //消费者名称
    public final String consumerName    = "emailConsumer";


    //注入模板
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

   
    //日志
    private static final Logger log = LoggerFactory.getLogger(ContinueDcouponControllerNew.class);

    @Override
    public void onMessage(MapRecord<String, String, String> message) {
        log.warn("[消费者]Stream名称{}消息内容{}",streamName,message.getValue());

        //获取生产者消息
        Map<String, String> msgMap = message.getValue();


        //业务逻辑 略

        //ps:通过 msgMap.get("key")  拿到需要参数执行业务逻辑
          

        StreamOperations<String, String, String> streamOperations = stringRedisTemplate.opsForStream();
        //消息应答
        streamOperations.acknowledge( streamName,groupName,message.getId() );
    }
}

三、生产者


/**
 *  接口代码
 */
@RestController
public class ContinueDcouponController {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    @PostMapping("/continueDcouponNew")
    public String continueDcoupon(String test) {
        
        //业务逻辑 略

        //创建Stream
        StreamOperations streamOperations = redisTemplate.opsForStream();
        //生产者发送消息  "emailStream"-是消费者配置的Stream队列名称
        streamOperations.add("emailStream",test);

        return "Success"
    }
}

四、Redis-Stream配置

@Configuration
public class RedisStreamConfig {

    //注入RedisConsumer
    @Autowired
    private RedisConsumer emailConsumer; 
    //注入Redis模板
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Bean
    public StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String,String,String>> emailListenerContainerOptions(){

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        return StreamMessageListenerContainer.StreamMessageListenerContainerOptions
                .builder()
                //block读取超时时间
                .pollTimeout(Duration.ofSeconds(3))
                //count 数量(一次只获取一条消息)
                .batchSize(1)
                //序列化规则
                .serializer( stringRedisSerializer )
                .build();
    }

    /**
     * 开启监听器接收消息
     */
    @Bean
    public StreamMessageListenerContainer<String,MapRecord<String,String,String>> emailListenerContainer(RedisConnectionFactory factory,
                                                                                                         StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String,String,String>> streamMessageListenerContainerOptions){

        StreamMessageListenerContainer<String,MapRecord<String,String,String>> listenerContainer = StreamMessageListenerContainer.create(factory,
                streamMessageListenerContainerOptions);

        //如果 流不存在 创建 stream 流
        if( !redisTemplate.hasKey(emailConsumer.streamName)){
            redisTemplate.opsForStream().add(emailConsumer.streamName, Collections.singletonMap("", ""));
            //log.info("初始化stream {} success",emailConsumer.streamName);
            System.out.println("初始化stream+"+emailConsumer.streamName+"成功!");
        }

        //创建消费者组
        try {
            redisTemplate.opsForStream().createGroup(emailConsumer.streamName,emailConsumer.groupName);
        } catch (Exception e) {
            //log.info("消费者组 {} 已存在",emailConsumer.groupName);
            System.out.println("消费者组"+ emailConsumer.groupName+"已存在");
        }

        //注册消费者 消费者名称,从哪条消息开始消费,消费者类
        // > 表示没消费过的消息
        // $ 表示最新的消息
        listenerContainer.receive(
            Consumer.from(emailConsumer.groupName, emailConsumer.consumerName),
            StreamOffset.create(emailConsumer.streamName, ReadOffset.lastConsumed()),
            emailConsumer
        );
        listenerContainer.start();
        return listenerContainer;
    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值