开发者社区> 海南三白> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
推荐Go语言开源项目:Excelize ,获取阿里云ECS实例监控数据导出到自定义Excel表格(二)
推荐Go语言开源项目:Excelize ,获取阿里云ECS实例监控数据导出到自定义Excel表格(二)
0 0
推荐Go语言开源项目:Excelize ,Go语言创建自定义Excel表格(一)
推荐Go语言开源项目:Excelize ,Go语言创建自定义Excel表格(一)
0 0
持续更新:Go语言常用语句总结
持续更新:Go语言常用语句总结
0 0
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
0 0
Go语言,修改其他函数内部的值
Go语言,修改其他函数内部的值
0 0
Go语言,panic和recover 遇到错误继续处理
Go语言,panic和recover 遇到错误继续处理
0 0
Go语言 数组、切片、map的区别
Go语言 数组、切片、map的区别
0 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Golang 微服务在腾讯游戏用户运营领域的探索及实践
立即下载
阿里云栖开发者沙龙PHP技术专场-RabbitMQ 的延时队列和镜像队列原理与实战-钱文品
立即下载
QQ移动页面框架优化实践
立即下载