Golang拿走不谢系列 - 电商系统短信消息发送优先级怎么实现

简介: 场景1:在电商系统中,会有下订单之后发送信息提示给用户。 场景2:订单这么久了还没发放,怎么办啊,我是硬硬点击提醒发货,给商家发送提示消息啊 场景3:现在很流行快递柜,小哥哥把快递放进柜子后,就当当当给手机用户发提示信息。

场景1:在电商系统中,会有下订单之后发送信息提示给用户。

场景2:订单这么久了还没发放,怎么办啊,我是硬硬点击提醒发货,给商家发送提示消息啊

场景3:现在很流行快递柜,小哥哥把快递放进柜子后,就当当当给手机用户发提示信息。

事实:流量小的话,请忽略。流量稍微大一点的电商,都不会按照信息的发送顺序来给用户发送提示的;商家不会按照消息的顺序发送消息提醒的,一般都会有一个规则,这个规则跟毛爷爷有关系,谁能贡献更多的毛爷爷,那么消息就会越优先发送。

解决方案:为了不影响下单流程的体验感,一般用MQ做解耦,将提示信息交给另外的系统去做。如果团队用的MQ自带优先级还好,不然的话,自己在信息系统中实现一个也不是什么难事。

我再实际应用中,也处理过类似的问题,那么以下就将代码分享出来(由于涉及到保密协议,敏感部分已经去掉,复制黏贴过去可进行扩展开发):

  1. 定义我们需要用到的结构体:

type Notice struct {
    Weight        int            // 值大者,优先发送
    PhoneNumber    string        // 对方手机号码
    Message        string        // 发送的提示信息
    index        int
}

type Notices []*Notice
  1. 定义我们需要用到的插入和弹出:

func (q *Notices) Push(n interface{}) {
    length := len(*q)
    capacity := cap(*q)
    if length + 1 > capacity {
        tq := make(Notices, length, capacity * 2)
        copy(tq, *q)
        *q = tq
    }
    *q = (*q)[0 : length + 1]
    ne := n.(*Notice)
    ne.index = length
    (*q)[length] = ne
    q.up(length)
}

func (q *Notices) Pop() interface{} {
    length := len(*q)
    capacity := cap(*q)
    (*q)[0], (*q)[length-1] = (*q)[length-1], (*q)[0]
    q.down(0, length-1)
    
    if length < (capacity / 2) && capacity > 25 {
        tq := make(Notices, length, capacity / 2)
        copy(tq, *q)
        *q = tq
    }
    ne := (*q)[length - 1]
    ne.index = -1
    *q = (*q)[0 : length - 1]
    return ne
}
  1. 定义我们进行调整的函数:


func (q *Notices) up(length int) {
    for {
        i := (length-1)/2
        if length == i || (*q)[i].Weight > (*q)[length].Weight {
            break
        }
        (*q)[i], (*q)[length] = (*q)[length], (*q)[i]
        length = i
    }
}

func (q *Notices) down(i, length int) {
    index := i
    for {
        left := 2 * index + 1
        if left >= length || left < 0 {
            break
        }
        swap := left;
        if right := left + 1; right < length && (*q)[right].Weight > (*q)[left].Weight {
            swap = right
        }
        
        if (*q)[swap].Weight < (*q)[index].Weight {
            break
        }
        
        (*q)[index], (*q)[swap] = (*q)[swap], (*q)[index]
        index = swap
    }
}

下面就用一下测试代码吧:


func main() {
    notices := make(Notices, 0, 100)
    fmt.Println(notices)
    for len(notices) < 30 {
        d := rand.Intn(1000-100)+100
        notice := &Notice{
            Weight:         d,
            PhoneNumber:    "13000000000",
            Message:        "我是通知消息",
        }
        fmt.Printf("add %d\n", d)
        notices.Push(notice)
    }
    
    for len(notices) > 0 {
        n := notices.Pop()
        ne := n.(*Notice)
        fmt.Printf("Pop %d\n", ne.Weight)
    }
}
相关文章
|
3月前
|
Java Go C++
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
15 0
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
|
10天前
|
Go
go语言中的数据类型
go语言中的数据类型
11 0
|
15天前
|
Go 开发者
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
|
15天前
|
安全 Go
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
掌握Go语言:Go语言通道,并发编程的利器与应用实例(20)
|
16天前
|
存储 缓存 安全
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)
|
16天前
|
Go
使用Go语言发邮件
使用Go语言发邮件
20 2
|
27天前
|
缓存 安全 Java
Go语言小细节
Go语言小细节
36 0
|
15天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
10天前
|
存储 Java 编译器
go语言基础语法
go语言基础语法