真实落地的高并发案例

发布于:2024-05-07 ⋅ 阅读:(24) ⋅ 点赞:(0)

1. 追根溯源

在弄清楚我们要做一个什么样的系统之前,先来解答一下我们为什么做这个系统,这不得不追溯过去。

目前线上虽然有旧系统提供服务,但旧系统不支持高并发,不易扩展,为了应对未来业务需要,所以我们就萌生了重建系统的想法。

但我们必须回答为什么不在原来的系统上进行重构,而要重建一个系统呢?

成本,成本,还是成本,当重建一个系统的成本小于重构的时候,重建是最佳选择。

顺便说说重构的事情

重构是一个比较常见的技术手段,但近些年逐步变成了贬义词,因为有相当一批技术人在不分青红皂白的情况下,重复创造轮子,导致了资源浪费,风气一度刮到互联网上,大家对重构望而生畏,一说起重构就被鄙视。

重构本身是健康的,是让代码变得更好的技术手段,当然不排除重构完之后,代码依然很烂,但这也是由个别程序员导致的。

给大家推荐一本书,Martin Fowler 他老人家的《重构:改善既有代码的设计》,这本书值得你看。

2.如何建设高并发系统

在我们选择了重建之后,接下来我们面对的课题是,我们要打造一个什么样的系统以及如何建造它。 我们要从两方面来谈这个事情。

2.1 核心业务模型

2.1.1 业务流程

在弄清楚核心业务模型之前,我们先看看我们的业务流程

业务流程

  1. 给用户创建一个抽奖池子,命名为awardPool,里边可以放很多奖券
  2. 系统自动从awardPool分配一个奖券给用户。
  3. 用户拿着已经抓到奖券去领取奖品。

通过核心流程我们可以看到两个关键字,抽奖池和奖券,下图是我们的核心业务模型

Description

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 提升系统可用性通常的做法

mindmap
      四种方式
            故障转移
             主备模式
             双活
            快速失败
            复制
             主从复制
             双主复制
             无主复制
            分区
    

说说故障转移

主备模式:通过心跳在主备之间进行探测,如果主机心跳中断,备机就会取代主机

双活:其中一个故障了,由另外一个提供服务,不需要进行选主,因为是双主,很多公司现在都做多云双机房,服务更加稳定,当然额外的成本也非常高。

说说复制

主从复制:master接收写操作,然后由master复制给其他副本,常见的mysql架构

双主复制:两个master都接收写,互相同步,然后再同步到其他副本,常用的双活模式下的数据同步方式。

无主复制:我理解跟双主复制是一样的,每个节点都可以接收写操作,然后互相同步,比如像Redis

说到以上数据同步方式,不得不提到保证数据一致性的一些协议

paxos:强一致性协议,因晦涩难懂,没有落地的方案。

Raft:强一致性协议,完善了paxos的晦涩难懂,实现了落地。

ZAB:强一致性协议,zookeeper在用

Gossip:八卦协议,redis在用

关于协议的原理,大家可以google一下原理,比我讲的好的太多了。

说说分区

什么是副本呢,顾名思义是把同样一份数据复制成多份,这样做的目的是防止数据因为丢失影响系统运行。

分区是把一整份数据切割成不同的小份,提升性能。

通常副本和分区一块使用,比如把一份数据分割成N份,每份都有多个副本,这样做既提升了系统的性能又防止数据的丢失。

总结

其实你看做一个软件系统并非是容易的事情,既要理解业务又要选对技术方案,关于技术,本文中也有好多没提到,比如扩容,在应对流量激增的常用技术手段,也是非常重要。做系统需要沉下心来思考,搞清楚每个概念以及概念之间的联系,这样做出来的系统更容易落地。