本文属于架构训练营学习笔记系列:模块3的案例讲解
总的来说,这篇从更高的维度去讲,而不是关注消息队列的常见问题:比如消息如何发送,消息如何不丢失 ,消息如何不重复。总体上分为2部分:利益干系人分析和复杂度分析、备选架构设计。
注意:这个案例得结合李老师当时所在公司的背景,2014年uc 刚被阿里收购的情况。放到现在再说自研mq.大概率会被否掉的,因为常见的kafka,rocketmq 基本上能满足需求,即使有个性化的需求,方案也可以考虑基于rocketmq做定制化改动。这里主要是看基于当时的情况,去做架构设计的一个思路。
背景:
1.中间件团队规模不大,大约6人左右。
2.中间件团队熟悉Java语言,但有一个同事C/C++很牛。
3.开发平台是Linux,数据库是MySQL。
4.目前整个业务系统是单机房部署,没有双机房。
5.刚刚被阿里以创纪录的金额收购。
这些需要 实地考虑的制约架构的因素。
利益干系人分析
这里跟模块3之前文章类似,这里从架构角度很重要,搞不定后面就没法开展。
利益干系人诉求排序
可用性:业务优先考虑可用性(就是不能因为mq丢失消息影响业务)
可维护性:各种维护操作要方便,例如收发消息情况、权限控制、上下线等
成本:开发成本不能太高
复杂度分析
高性能:不需要高性能,游戏新版本发布和VIP充值的消息并不多
这里不要误会,不要高性能,也得满足业务需求。
高可用:需要,游戏版本发布和VIP都是高优先级业务
可扩展:不需要,消息队列的功能基本明确,无需扩展
成本:开发投入人力和时间不能太长
备选架构:
备选架构1 kafka
备选架构2-自研集群+MySQL存储
这个图有些抽象,不是常见的发送--》队列---》接受那种模型图
备选架构3-自研集群+自研存储
1.模拟Kafka的原理,用Java语言实现,也可以用LSM数据结构来存储消息
2.可以保证高可用高性能
3.加上可维护性的各种能力,嵌入到已有的运维体系
4 备选架构4-直接用阿里的MetaQ
架构决策
确定排序规则:1.可用性;2.可维护性;3.人力成本
评估后符合的只有方案2
详细架构
详细架构设计1-Role&Relation
【客户端Role设计】1.客户端采用Java语言开发,基于Netty实现与服务端交互
【服务器Role设计】1.服务器基于Netty开发,采用Reactor网络模型
2.两台服务器组成一个sharding,整个系统可以多个sharding,每个sharding包含一主一从两台服务器(可以对比MongoDBshard)
3.主服务器提供消息读写操作,从服务器只提供消息读取操作
4.服务器基于ZooKeeper进行主从切换
【客户端和服务器的Relation设计】
1.客户端与服务端采用TCP连接,采用Json传递数据
2.为了兼容非Java系统,服务端同时提供HTTP接口
【MySQL的Role和Relation设计】
1.采用MySQL主从同步
2.每个消息队列对应一个表
3.消息表最多存储30天内的消息,过期的自动清除
4.直接用MySQL的主从复制来实现数据复制
详细架构设计2-Rule
【消息发布】
1.消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称。
2.消息队列系统提供SDK供各业务系统调用,SDK从配置中读取所有消息队列系统的服务器信息,SDK采取轮询算法发起消息写入请求给主服务器。
3.如果某个主服务器无响应或者返回错误,SDK将发起请求发送到下一台主服务,相当于在客户端实现了分片的功能
【消息读取】
1.消息队列系统提供SDK供各业务系统调用,SDK从配置中读取所有消息队列系统的服务器信息,轮流向所有服务器发起消息读取请求。
2.消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。
3.默认情况下主服务器提供读写服务,当主服务器挂掉后,从服务器提供读消息服务
【服务器主从切换】
1.同一组的主从服务器配置相同的group名称,在ZooKeeper建立对应的PERSISENT节点
2.主从服务器启动后,在ZooKeeper对应的group节点下建立EPHEMERAL节点,名称分为为master和slave
3.从服务器watch主服务器的master节点状态,当master节点超时被删除后,从服务器接管读消息,收到客户端SDK的读消息请求后返回消息,收到客户端SDK的写请求直接拒绝。
消息队列管理系统
小结
这些架构还是挺抽象的,消息队列主要解决应用耦合,异步消息,流量削锋等问题,还可以结合之前那篇58到家mq【沈老师 架构师之路:MQ消息整理系列】_58mq.on_bohu83的博客-CSDN博客
来看,那篇更具体,细节更多。李老师讲了很多有趣的点,比如使用MySQL做消息队列存储通常会引起别人质疑,尤其是性能不达标的时候。分库分表这种得考虑好。为啥要引入HTTP接口,还是兼容其他语言调用,而不是对应去 开发SDK。后来他回忆,这个恰当的造轮子在他考核升级的时候发挥了重大作用,也算是一个主要业绩点。