1. 追根溯源
在弄清楚我们要做一个什么样的系统之前,先来解答一下我们为什么做这个系统,这不得不追溯过去。
目前线上虽然有旧系统提供服务,但旧系统不支持高并发,不易扩展,为了应对未来业务需要,所以我们就萌生了重建系统的想法。
但我们必须回答为什么不在原来的系统上进行重构,而要重建一个系统呢?
成本,成本,还是成本,当重建一个系统的成本小于重构的时候,重建是最佳选择。
顺便说说重构的事情
重构是一个比较常见的技术手段,但近些年逐步变成了贬义词,因为有相当一批技术人在不分青红皂白的情况下,重复创造轮子,导致了资源浪费,风气一度刮到互联网上,大家对重构望而生畏,一说起重构就被鄙视。
重构本身是健康的,是让代码变得更好的技术手段,当然不排除重构完之后,代码依然很烂,但这也是由个别程序员导致的。
给大家推荐一本书,Martin Fowler 他老人家的《重构:改善既有代码的设计》,这本书值得你看。
2.如何建设高并发系统
在我们选择了重建之后,接下来我们面对的课题是,我们要打造一个什么样的系统以及如何建造它。 我们要从两方面来谈这个事情。
2.1 核心业务模型
2.1.1 业务流程
在弄清楚核心业务模型之前,我们先看看我们的业务流程
- 给用户创建一个抽奖池子,命名为awardPool,里边可以放很多奖券
- 系统自动从awardPool分配一个奖券给用户。
- 用户拿着已经抓到奖券去领取奖品。
通过核心流程我们可以看到两个关键字,抽奖池和奖券,下图是我们的核心业务模型
2.1.2 模块划分
从业务流程我们可以分析得知,我们的系统至少有三个模块
模块名称 | 核心功能 | 输入 | 输出 | 描述 |
---|---|---|---|---|
awardMgtService | 负责奖券池的创建,创建奖券,手动分配奖券给用户,手动兑换奖券等 | 提供用户信息 | 奖券池 | 奖券管理服务 |
awardAssignService | 自动从奖券池分配奖券 | 奖券池ID | 分配一个奖券 | 自动分配奖券服务 |
awardReceiveService | 兑换奖券 | 奖券信息 | 奖品 | 兑换奖品服务 |
2.2 技术指标
2.2.1 系统容量
在说完核心业务之后,我们来一起聊聊核心技术指标,怎么衡量一个系统具备高并发的能力,我们给出了以下指标
模块 | 指标 | 计算方式 | 统计方式 | 结果 |
---|---|---|---|---|
awardMgtService | 创建奖券成功率 | 每秒的成功数/每秒的请求总数 | 监控埋点 | 99.99% |
awardAssignService | 自动分配券成功率 | 每秒的自动分配奖券成功数/每秒的请求总数 | 监控埋点 | 99.99% |
QPS | 每秒请求总数 | 监控埋点 | 1w QPS TP95延时 50ms | |
awardReceiveService | 兑换奖券成功率 | 每秒的兑换成功数/每秒的请求总数 | 监控埋点 | 99.99% |
QPS | 每秒请求总总数 | 监控埋点 | 2w QPS TP95延时 30ms |
除此之外,做系统设计还需要考虑什么吗?
2.2.2 稳定性
关于稳定性,亚马逊是这么定义的
系统稳定性是指一个系统在特定环境和负载下能够持续运行,不会出现严重的故障、崩溃或异常行为的特性
2.2.2.1 稳定性问题都有哪些呢?
故障分类 | 说明 |
---|---|
硬件故障 | 比如cpu,内存,磁盘故障 |
软件故障 | 业务系统bug,中间件故障 |
配置错误 | 由人为导致的配置错误 |
网络问题 | 网络攻击等 |
我这里只是列出了大概的分类,除了这些已知的因素之外,还有一些不可抗力的因素,比如一辆大卡车不小心冲进了机房,从而把电缆撞断了。 千万别以为这是笑话,这是曾经发生过的故事。
2.2.2.2 如何识别这些问题呢?
监控,监控,还是监控。
我们都做过体检,体检是一种主动行为,时不时定期的去检查一下身体,看看是否存在问题。 有时候有些急症,去医院挂急诊,医院急诊的处理的流程会更快一些,这是我们的被动行为。
监控可以帮我们发现系统中可能存在的问题,比如当我们发现mysql的cpu利用率>60%的时候,我们可以主动干预。 当系统中发生一些异常的时候,监控帮助识别问题。
在我过去的工作经历中,我见过好多系统简直就是在裸奔,系统上线之后,没有任何监控的手段,系统运行的怎么样,一概不知,只有出了问题产生了损失才去修复,这实在是太可怕了。
监控是一双眼睛,帮助我们查看系统运行的状况
除了监控之外,我们可以通过性能测试,code Review等手段尽早发现一些问题,像findBugs、sonar等代码扫描插件也可以帮助提前发现问题。
2.2.3 可用性
维基百科的定义
可用性就是一个系统处在可工作状态的时间的比例。这通常被描述为任务可行率
一天按照24小时计算,麦当劳只有1小时不外卖,那
可用率=23/24*100%=95.83%
2.2.3.1 如何衡量系统的可用性,通常的做法是几个9
可用性 | 最高的無法使用程度 (每年) | 系统分类 |
---|---|---|
99% | 3 天 15 小時 | 批次處理、資料擷取、傳輸和載入任務 |
99.9% | 8 小時 45 分钟 | 知識管理、專案追蹤等內部工具 |
99.95% | 4 小時 22 分鐘 | 線上商務、銷售點 |
99.99% | 52 分鐘 | 影片交付、廣播工作負載 |
99.999% | 5 分鐘 | ATM 交易、電信工作負載 |
2.2.3.2 提升系统可用性通常的做法
说说故障转移
主备模式:通过心跳在主备之间进行探测,如果主机心跳中断,备机就会取代主机 双活:其中一个故障了,由另外一个提供服务,不需要进行选主,因为是双主,很多公司现在都做多云双机房,服务更加稳定,当然额外的成本也非常高。
说说复制
主从复制:master接收写操作,然后由master复制给其他副本,常见的mysql架构 双主复制:两个master都接收写,互相同步,然后再同步到其他副本,常用的双活模式下的数据同步方式。 无主复制:我理解跟双主复制是一样的,每个节点都可以接收写操作,然后互相同步,比如像Redis
说到以上数据同步方式,不得不提到保证数据一致性的一些协议
paxos:强一致性协议,因晦涩难懂,没有落地的方案。
Raft:强一致性协议,完善了paxos的晦涩难懂,实现了落地。
ZAB:强一致性协议,zookeeper在用
Gossip:八卦协议,redis在用
关于协议的原理,大家可以google一下原理,比我讲的好的太多了。
说说分区
什么是副本呢,顾名思义是把同样一份数据复制成多份,这样做的目的是防止数据因为丢失影响系统运行。
分区是把一整份数据切割成不同的小份,提升性能。
通常副本和分区一块使用,比如把一份数据分割成N份,每份都有多个副本,这样做既提升了系统的性能又防止数据的丢失。
总结
其实你看做一个软件系统并非是容易的事情,既要理解业务又要选对技术方案,关于技术,本文中也有好多没提到,比如扩容,在应对流量激增的常用技术手段,也是非常重要。做系统需要沉下心来思考,搞清楚每个概念以及概念之间的联系,这样做出来的系统更容易落地。