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)
    }
}
相关文章
|
4月前
|
Go
Golang语言常用的操作符优先级及获取用户终端输入的两种方式
这篇文章介绍了Golang语言中常用的算术、赋值、关系、逻辑、位运算符以及指针运算符的使用,运算符优先级,以及如何通过Scanln和Scanf函数获取用户终端输入的两种方式。
25 0
|
8月前
|
Java Go C++
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
31 0
Golang每日一练(leetDay0090) 运算优先级、有效字母异位词
|
19天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
63 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
1月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
42 7
|
1月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
1月前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
106 71
|
1月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
109 67
|
1月前
|
Go 索引
go语言for遍历数组或切片
go语言for遍历数组或切片
107 62
|
4天前
|
监控 安全 算法
深度剖析核心科技:Go 语言赋能局域网管理监控软件进阶之旅
在局域网管理监控中,跳表作为一种高效的数据结构,能显著提升流量索引和查询效率。基于Go语言的跳表实现,通过随机化索引层生成、插入和搜索功能,在高并发场景下展现卓越性能。跳表将查询时间复杂度优化至O(log n),助力实时监控异常流量,保障网络安全与稳定。示例代码展示了其在实际应用中的精妙之处。
27 9
|
14天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
47 12