golang redis stream 消息队列实现 模拟生产者和消费者

目录

一、需要注意一个问题

已知问题:

二、代码如下

生产者:

消费者:

三、测试结果


一、需要注意一个问题

客户端使用go-redis库  "github.com/go-redis/redis",不要使用"github.com/redis/go-redis/v9"

已知问题

使用go-redis/v9 会带来消费消息延时上涨

二、代码如下

生产者:
package main

import (
	"fmt"
	"log"
	"math/rand"
	"time"

	"github.com/go-redis/redis"
)

func publishTicketReceivedEvent(client *redis.Client) error {
	log.Println("Publishing event to Redis")
	startTime := time.Now().UnixNano() / 1000
	err := client.XAdd(&redis.XAddArgs{
		Stream:       "tickets",
		MaxLen:       0,
		MaxLenApprox: 0,
		ID:           "",
		Values: map[string]interface{}{
			"whatHappened": string("ticket received"),
			"ticketID":     int(rand.Intn(100000000)),
			"ticketData":   string("some ticket data"),
		},
	}).Err()
	stopTime := time.Now().UnixNano() / 1000
	log.Printf("生产者用时 %d 毫秒 \n", (stopTime-startTime)/1000)

	return err
}

func main() {
	log.Println("Publisher started")
	redisClient := redis.NewClient(&redis.Options{
		Addr:     fmt.Sprintf("%s:%s", "10.50.28.204", "32748"),
		Password: "xxxx",
		DB:       15,
	})
	_, err := redisClient.Ping().Result()
	if err != nil {
		log.Fatal("Unable to connect to Redis", err)
	}
	log.Println("Connected to Redis server")

	for i := 0; i < 3000; i++ {
		err = publishTicketReceivedEvent(redisClient)
		if err != nil {
			log.Fatal(err)
		}
	}
}
消费者:
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/go-redis/redis"
	// "github.com/redis/go-redis/v9"
	"github.com/rs/xid"
)

//func handleNewTicket(ticketID string, ticketData string) error {
//	log.Printf("Handling new ticket id : %s data %s\n", ticketID, ticketData)
//	return nil
//}

var ctx = context.Background()

func main() {
	log.Println("Consumer started")
	redisClient := redis.NewClient(&redis.Options{
		Addr:     fmt.Sprintf("%s:%s", "10.50.28.204", "32748"),
		Password: "xxxx",
		DB:       15,
	})

	_, err := redisClient.Ping(ctx).Result()
	if err != nil {
		log.Fatal("Unbale to connect to Redis", err)
	}
	log.Println("Connected to Redis server")

	subject := "tickets"
	consumersGroup := "tickets-consumer-group"
	err = redisClient.XGroupCreate(ctx, subject, consumersGroup, "0").Err()
	if err != nil {
		log.Println(err)
	}

	uniqueID := xid.New().String()
	for {
		startTime := time.Now().UnixNano() / 1000
		entries, err := redisClient.XReadGroup(ctx, &redis.XReadGroupArgs{
			Group:    consumersGroup,
			Consumer: uniqueID,
			Streams:  []string{subject, ">"},
			Count:    2,
			Block:    0,
			NoAck:    false,
		}).Result()
		if err != nil {
			log.Fatal(err)
		}
		for i := 0; i < len(entries[0].Messages); i++ {
			messageID := entries[0].Messages[i].ID
			values := entries[0].Messages[i].Values
			eventDescription := fmt.Sprintf("%v", values["whatHappened"])
			ticketID := fmt.Sprintf("%v", values["ticketID"])
			ticketData := fmt.Sprintf("%v", values["ticketData"])
			if eventDescription == "ticket received" {
				stopTime := time.Now().UnixNano() / 1000
				log.Printf("Handling new ticket id : %s data %s 用时 %d 毫秒 \n", ticketID, ticketData, (stopTime-startTime)/1000)
				//err := handleNewTicket(ticketID, ticketData,stopTime)
				//if err != nil {
				//	log.Fatal(err)
				//}
				redisClient.XAck(ctx, subject, consumersGroup, messageID)
			}
		}
	}
}

三、测试结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cloud孙文波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值