场景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)
    }
}