最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Redis實(shí)現(xiàn)輕量級消息隊列

 更新時間:2025年11月14日 10:08:48   作者:moxiaoran5753  
使用消息中間件如RabbitMQ或kafka雖然好,但也給服務(wù)器帶來很大的內(nèi)存開銷,當(dāng)系統(tǒng)的業(yè)務(wù)量,并發(fā)量不高時,考慮到服務(wù)器和維護(hù)成本,可考慮使用Redis實(shí)現(xiàn)一個輕量級的消息隊列,下面就來詳細(xì)的介紹一下

使用消息中間件如RabbitMQ或kafka雖然好,但也給服務(wù)器帶來很大的內(nèi)存開銷,當(dāng)系統(tǒng)的業(yè)務(wù)量,并發(fā)量不高時,考慮到服務(wù)器和維護(hù)成本,可考慮使用Redis實(shí)現(xiàn)一個輕量級的消息隊列,實(shí)現(xiàn)事件監(jiān)聽的效果。下面介紹下Redis實(shí)現(xiàn)消息隊列的三種形式。

方式一  Redis Pub/Sub(適用于廣播通知)

Redis Pub/Sub 適用于 實(shí)時消息推送,但不支持消息持久化,如果消費(fèi)者掉線,消息會丟失。

(1) 發(fā)布消息(生產(chǎn)者)

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    private final StringRedisTemplate redisTemplate;

    public OrderService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void createOrder(Long orderId) {
        System.out.println("訂單創(chuàng)建成功: " + orderId);

        // 發(fā)布消息
        redisTemplate.convertAndSend("order.channel", orderId.toString());
    }
}

(2) 訂閱消息(消費(fèi)者)

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Service;

@Service
public class NotificationService implements MessageListener {

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String orderId = message.toString();
        System.out.println("【通知服務(wù)】收到訂單創(chuàng)建消息:" + orderId);
    }
}

(3) 注冊 Redis 監(jiān)聽器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisPubSubConfig {

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic("order.channel"));
        return container;
    }

    @Bean
    public MessageListenerAdapter listenerAdapter(NotificationService receiver) {
        return new MessageListenerAdapter(receiver, "onMessage");
    }
}

缺點(diǎn)

  • 無持久化,消費(fèi)者掉線后無法重新獲取消息。
  • 不支持消費(fèi)組,多個消費(fèi)者同時訂閱時,所有都會收到消息(無法負(fù)載均衡)。

方式二:Redis List(適用于任務(wù)隊列)

使用 Redis ListLPUSH + RPOP)可以實(shí)現(xiàn)簡單的任務(wù)隊列,適用于任務(wù)異步處理,但不支持回溯消費(fèi)。

(1) 生產(chǎn)者(推送任務(wù))

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    private final StringRedisTemplate redisTemplate;

    public OrderService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void createOrder(Long orderId) {
        System.out.println("訂單創(chuàng)建成功: " + orderId);

        // 推送到隊列
        redisTemplate.opsForList().leftPush("order.queue", orderId.toString());
    }
}

(2) 消費(fèi)者(輪詢獲取任務(wù))

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class NotificationService {
    private final StringRedisTemplate redisTemplate;

    public NotificationService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Scheduled(fixedDelay = 5000) // 每5秒輪詢一次
    public void processOrderQueue() {
        String orderId = redisTemplate.opsForList().rightPop("order.queue");
        if (orderId != null) {
            System.out.println("【通知服務(wù)】處理訂單:" + orderId);
        }
    }
}

要想消費(fèi)者能監(jiān)聽到消息并進(jìn)行處理,需要在方法上添加@Scheduled注解,同時在服務(wù)啟動類中添加@EnableScheduling注解,或者在配置類添加

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableScheduling
public class SchedulingConfig {
}

缺點(diǎn)

  • 無消費(fèi)組,多個消費(fèi)者時需要自行分配任務(wù),可能會造成任務(wù)重復(fù)消費(fèi)或丟失。
  • 無持久化保障,如果任務(wù)未處理完,Redis 發(fā)生故障,任務(wù)可能會丟失。

方式三:Redis Stream(推薦,支持持久化 + 消費(fèi)組)

Redis Stream 是 Redis 6.0 之后的特性,類似于 Kafka,支持持久化、消費(fèi)組、多消費(fèi)者模式。

(1) 生產(chǎn)者(推送事件)

import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    private final StringRedisTemplate redisTemplate;

    public OrderService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void createOrder(Long orderId) {
        System.out.println("訂單創(chuàng)建成功: " + orderId);

        // 推送到 Redis Stream
        ObjectRecord<String, String> record = StreamRecords.newRecord()
                .ofObject(orderId.toString())
                .withStreamKey("order.stream");
        redisTemplate.opsForStream().add(record);
    }
}

(2) 消費(fèi)者(監(jiān)聽事件)

import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.ReadOffset;
import org.springframework.data.redis.connection.stream.StreamMessageListenerContainer;
import org.springframework.data.redis.connection.stream.StreamOffset;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.Collections;

@Service
public class NotificationService implements StreamListener<String, MapRecord<String, String, String>> {

    private final StringRedisTemplate redisTemplate;
    private final StreamMessageListenerContainer<String, MapRecord<String, String, String>> listenerContainer;

    public NotificationService(StringRedisTemplate redisTemplate,
                               StreamMessageListenerContainer<String, MapRecord<String, String, String>> listenerContainer) {
        this.redisTemplate = redisTemplate;
        this.listenerContainer = listenerContainer;
    }

    @PostConstruct
    public void startListening() {
        listenerContainer.receive(StreamOffset.fromStart("order.stream"), this);
    }

    @Override
    public void onMessage(MapRecord<String, String, String> message) {
        String orderId = message.getValue().values().iterator().next();
        System.out.println("【通知服務(wù)】訂單 " + orderId + " 創(chuàng)建成功!");
    }
}

優(yōu)點(diǎn)

  • 持久化存儲,即使 Redis 重啟,消息不會丟失。
  • 支持消費(fèi)組,多個消費(fèi)者可以負(fù)載均衡地消費(fèi)消息。
  • 支持回溯,可以讀取歷史消息。

總結(jié)

方案適用場景優(yōu)點(diǎn)缺點(diǎn)
Pub/Sub即時消息通知低延遲無持久化,消費(fèi)者掉線丟消息
List簡單任務(wù)隊列輕量級無消費(fèi)組,任務(wù)可能丟失
Stream高級事件流處理持久化、消費(fèi)組復(fù)雜度較高

如果需求是輕量級隊列,推薦 Redis Stream,它類似 Kafka,支持消費(fèi)組和持久化,比 Redis List 更穩(wěn)定。

到此這篇關(guān)于使用Redis實(shí)現(xiàn)輕量級消息隊列的文章就介紹到這了,更多相關(guān)Redis 輕量級消息隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題

    基于Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題

    這篇文章主要給大家介紹了使用Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2023-08-08
  • golang協(xié)程池模擬實(shí)現(xiàn)群發(fā)郵件功能

    golang協(xié)程池模擬實(shí)現(xiàn)群發(fā)郵件功能

    這篇文章主要介紹了golang協(xié)程池模擬實(shí)現(xiàn)群發(fā)郵件功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • linux下通過go語言獲得系統(tǒng)進(jìn)程cpu使用情況的方法

    linux下通過go語言獲得系統(tǒng)進(jìn)程cpu使用情況的方法

    這篇文章主要介紹了linux下通過go語言獲得系統(tǒng)進(jìn)程cpu使用情況的方法,實(shí)例分析了Go語言使用linux的系統(tǒng)命令ps來分析cpu使用情況的技巧,需要的朋友可以參考下
    2015-03-03
  • golang的HTTP基本認(rèn)證機(jī)制實(shí)例詳解

    golang的HTTP基本認(rèn)證機(jī)制實(shí)例詳解

    這篇文章主要介紹了golang的HTTP基本認(rèn)證機(jī)制,結(jié)合實(shí)例形式較為詳細(xì)的分析了HTTP請求響應(yīng)的過程及認(rèn)證機(jī)制實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-07-07
  • Go語言中的Web服務(wù)器開發(fā)詳細(xì)指南

    Go語言中的Web服務(wù)器開發(fā)詳細(xì)指南

    go提供了一系列用于創(chuàng)建web服務(wù)器的標(biāo)準(zhǔn),而非常簡單,下面這篇文章主要給大家介紹了關(guān)于Go語言中Web服務(wù)器開發(fā)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-07-07
  • Go使用協(xié)程交替打印字符

    Go使用協(xié)程交替打印字符

    這篇文章主要介紹了Go使用協(xié)程交替打印字符,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 一文帶你了解Golang中reflect反射的常見錯誤

    一文帶你了解Golang中reflect反射的常見錯誤

    go?反射的錯誤大多數(shù)都來自于調(diào)用了一個不適合當(dāng)前類型的方法,?而且,這些錯誤通常是在運(yùn)行時才會暴露出來,而不是在編譯時,如果我們傳遞的類型在反射代碼中沒有被覆蓋到那么很容易就會?panic。本文就介紹一下使用?go?反射時很大概率會出現(xiàn)的錯誤,需要的可以參考一下
    2023-01-01
  • golang語言http協(xié)議get拼接參數(shù)操作

    golang語言http協(xié)議get拼接參數(shù)操作

    這篇文章主要介紹了golang語言http協(xié)議get拼接參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang定時任務(wù)框架GoCron的源碼分析

    Golang定時任務(wù)框架GoCron的源碼分析

    本文主要介紹了Golang定時任務(wù)框架GoCron的源碼分析,原生的gocron存在一些問題,如任務(wù)列表維護(hù)不當(dāng)、并發(fā)操作不可預(yù)測等,經(jīng)過改進(jìn)的gocron解決了這些問題,感興趣的可以了解一下
    2025-03-03
  • 解讀go在遍歷map過程中刪除成員是否安全

    解讀go在遍歷map過程中刪除成員是否安全

    在Go語言中,通過for range遍歷map時可以安全地刪除當(dāng)前遍歷到的元素,因為遍歷過程中的刪除操作不會影響遍歷的進(jìn)行,但需要注意,遍歷順序是不確定的,刪除元素不會導(dǎo)致程序錯誤,但可能會影響剩余元素的遍歷順序,在多線程環(huán)境下
    2024-09-09

最新評論

永康市| 唐山市| 远安县| 家居| 贵港市| 宝兴县| 锡林浩特市| 舟曲县| 青浦区| 白城市| 肃宁县| 密云县| 新竹县| 平乐县| 团风县| 新巴尔虎右旗| 嘉黎县| 聂拉木县| 广宗县| 波密县| 平远县| 沿河| 绥阳县| 夏河县| 抚松县| 和平县| 杂多县| 乌兰浩特市| 卓尼县| 五寨县| 邹城市| 阿克陶县| 大渡口区| 海城市| 新津县| 合水县| 绥棱县| 贵定县| 隆德县| 凉城县| 嘉定区|