写点什么

第五周总结

用户头像
武鹏
关注
发布于: 2020 年 07 月 06 日

这周老师将了 缓存 消息队列 负载均衡 分布式数据库

缓存: 最常用 最有效的提升性能的手段

缓存命中率是缓存的主要指标,有 3 个影响因素:key 集合大小、内存大小、TTL 生存时间

CDN 内容分发网络也是一种常用手段



memcached 分布式缓存 客户端的一致性 hash 算法用于路由选择


redis cluster 集群用作分布式缓存


缓存穿透

在高并发下,查询一个不存在的值时,缓存不会被命中,导致大量请求直接落到数据库上,如活动系统里面查询一个不存在的活动。

缓存击穿

在高并发下,对一个特定的值进行查询,但是这个时候缓存正好过期了,缓存没有命中,导致大量请求直接落到数据库上,如活动系统里面查询活动信息,但是在活动进行过程中活动缓存突然过期了。

缓存雪崩

在高并发下,大量的缓存 key 在同一时间失效,导致大量的请求落到数据库上,如活动系统里面同时进行着非常多的活动,但是在某个时间点所有的活动缓存全部过期。

常见解决方案

  • 直接缓存 NULL 值

  • 限流

  • 缓存预热

  • 分级缓存

  • 缓存永远不过期


消息队列

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题

实现高性能,高可用,可伸缩和最终一致性架构

使用较多的消息队列有 ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ

kafka与Rocketmq的区别

淘宝内部的交易系统使用了淘宝自主研发的 Notify 消息中间件,使用 Mysql 作为消息存储媒介,可完全水平扩容,为了进一步降低成本,我们认为存储部分可以进一步优化,2011 年初,Linkin 开源了 Kafka 这个优秀的消息中间件,淘宝中间件团队在对 Kafka 做过充分 Review 之后,Kafka 无限消息堆积,高效的持久化速度吸引了我们,但是同时发现这个消息系统主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足,为此我们重新用 Java 语言编写了 RocketMQ,定位于非日志的可靠消息传输(日志场景也 OK),目前 RocketMQ 在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog 分发等场景。

数据可靠性

  • RocketMQ 支持异步实时刷盘,同步刷盘,同步 Replication,异步 Replication

  • Kafka 使用异步刷盘方式,异步 Replication

总结:RocketMQ 的同步刷盘在单机可靠性上比 Kafka 更高,不会因为操作系统 Crash,导致数据丢失。 同时同步 Replication 也比 Kafka 异步 Replication 更可靠,数据完全无单点。另外 Kafka 的 Replication 以 topic 为单位,支持主机宕机,备机自动切换,但是这里有个问题,由于是异步 Replication,那么切换后会有数据丢失,同时 Leader 如果重启后,会与已经存在的 Leader 产生数据冲突。开源版本的 RocketMQ 不支持 Master 宕机,Slave 自动切换为 Master,阿里云版本的RocketMQ支持自动切换特性。

性能对比

总结:Kafka 的 TPS 跑到单机百万,主要是由于 Producer 端将多个小消息合并,批量发向 Broker。

RocketMQ 为什么没有这么做?

  1. Producer 通常使用 Java 语言,缓存过多消息,GC 是个很严重的问题

  2. Producer 调用发送消息接口,消息未发送到 Broker,向业务返回成功,此时 Producer 宕机,会导致消息丢失,业务出错

  3. Producer 通常为分布式系统,且每台机器都是多线程发送,我们认为线上的系统单个 Producer 每秒产生的数据量有限,不可能上万。

  4. 缓存的功能完全可以由上层业务完成。

单机支持的队列数

  • Kafka 单机超过 64 个队列/分区,Load 会发生明显的飙高现象,队列越多,load 越高,发送消息响应时间变长

  • RocketMQ 单机支持最高 5 万个队列,Load 不会发生明显变化

队列多有什么好处?

  1. 单机可以创建更多 Topic,因为每个 Topic 都是由一批队列组成

  2. Consumer 的集群规模和队列数成正比,队列越多,Consumer 集群可以越大

消息投递实时性

  • Kafka 使用短轮询方式,实时性取决于轮询间隔时间

  • RocketMQ 使用长轮询,同 Push 方式实时性一致,消息的投递延时通常在几个毫秒。

消费失败重试

  • Kafka 消费失败不支持重试

  • RocketMQ 消费失败支持定时重试,每次重试间隔时间顺延

总结:例如充值类应用,当前时刻调用运营商网关,充值失败,可能是对方压力过多,稍后在调用就会成功,如支付宝到银行扣款也是类似需求。

这里的重试需要可靠的重试,即失败重试的消息不因为 Consumer 宕机导致丢失。

严格的消息顺序

  • Kafka 支持消息顺序,但是一台 Broker 宕机后,就会产生消息乱序

  • RocketMQ 支持严格的消息顺序,在顺序消息场景下,一台 Broker 宕机后,发送消息会失败,但是不会乱序

Mysql Binlog 分发需要严格的消息顺序

定时消息

  • Kafka 不支持定时消息

  • RocketMQ 支持两类定时消息开源版本 RocketMQ 仅支持定时 Level 阿里云 ONS 支持定时 Level,以及指定的毫秒级别的延时时间

分布式事务消息

  • Kafka 不支持分布式事务消息

  • 阿里云 ONS 支持分布式定时消息,未来开源版本的 RocketMQ 也有计划支持分布式事务消息

消息查询

  • Kafka 不支持消息查询

  • RocketMQ 支持根据 Message Id 查询消息,也支持根据消息内容查询消息(发送消息时指定一个 Message Key,任意字符串,例如指定为订单 Id)

总结:消息查询对于定位消息丢失问题非常有帮助,例如某个订单处理失败,是消息没收到还是收到处理出错了。

消息回溯

  • Kafka 理论上可以按照 Offset 来回溯消息

  • RocketMQ 支持按照时间来回溯消息,精度毫秒,例如从一天之前的某时某分某秒开始重新消费消息

总结:典型业务场景如 consumer 做订单分析,但是由于程序逻辑或者依赖的系统发生故障等原因,导致今天消费的消息全部无效,需要重新从昨天零点开始消费,那么以时间为起点的消息重放功能对于业务非常有帮助。

消费并行度

  • Kafka 的消费并行度依赖 Topic 配置的分区数,如分区数为 10,那么最多 10 台机器来并行消费(每台机器只能开启一个线程),或者一台机器消费(10 个线程并行消费)。即消费并行度和分区数一致。

  • RocketMQ 消费并行度分两种情况

消息轨迹

  • Kafka 不支持消息轨迹

  • 阿里云 ONS 支持消息轨迹

开发语言友好性

  • Kafka 采用 Scala 编写

  • RocketMQ 采用 Java 语言编写

Broker 端消息过滤

  • Kafka 不支持 Broker 端的消息过滤

  • RocketMQ 支持两种 Broker 端消息过滤方式根据 Message Tag 来过滤,相当于子 topic 概念向服务器上传一段 Java 代码,可以对消息做任意形式的过滤,甚至可以做 Message Body 的过滤拆分。

消息堆积能力

理论上 Kafka 要比 RocketMQ 的堆积能力更强,不过 RocketMQ 单机也可以支持亿级的消息堆积能力,我们认为这个堆积能力已经完全可以满足业务需求。

开源社区活跃度

商业支持

成熟度

  • Kafka 在日志领域比较成熟

  • RocketMQ 在阿里集团内部有大量的应用在使用,每天都产生海量的消息,并且顺利支持了多次天猫双十一海量消息考验,是数据削峰填谷的利器。


负载均衡

常用的有 nginx 和 lvs

nginx 和 LVS 作对比的结果:

  1. nginx 工作在网络的第 7 层,可以作为网页静态服务器,支持 Rewrite 重写规则;支持 GZIP 压缩,节省带宽;可以做缓存;可以针对 http 应用本身来做分流策略,静态分离,针对域名、目录结构等

相比之下 LVS 并不具备这样的功能,所以 nginx 单凭这点可以利用的场合就远多于 LVS 了;但 nginx 有用的这些功能使其可调整度要高于 LVS,所以经常要去触碰,人为出现问题的几率也就大


nginx 对网络的依赖较小,理论上只要 ping 得通,网页访问正常,nginx 就能连得通,nginx 同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS 就比较依赖于网络环境,目前来看服务器在同一网段内并且 LVS 使用 direct 方式分流,效果较能得到保证。另外注意,LVS 需要向托管商至少申请多于一个 ip 来做 visual ip

nginx 安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS 的安装和配置、测试就要花比较长的时间,因为同上所述,LVS 对网络依赖性比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦的多

nginx 也同样能承受很高负载且稳定,但负载度和稳定度差 LVS 还有几个等级:nginx 处理所有流量所以受限于机器 IO 和配置;本身的 bug 也还是难以避免的;nginx 没有现成的双机热备方案,所以跑在单机上还是风险比较大,单机上的事情全都很难说

nginx 可以检测到服务器内部的故障(健康检查),比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前 LVS 中 ldirectd 也能支持针对服务器内部的情况来监控,但 LVS 的原理使其不能重发请求。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,nginx 会把上传切到另一台服务器重新处理,而 LVS 就直接断掉了

适用业务场景

  1. 网站建设初期(每日 PV 小于 100 万),可以选用 Nigix 作为反向代理负载均衡,因为其配置简单,性能也能满足一般的业务场景。如果考虑到负载均衡器是有单点问题,可以采用 Nginx + Keepalived 避免负载均衡器自身的单点问题

  2. 网站并发达到一定程度之后,为了提高稳定性和转发效率,可以使用 LVS、毕竟 LVS 比 Nginx 要更稳定,转发效率也更高。不过维护 LVS 对维护人员的要求也会更高,投入成本也更大


分布式数据库

mysql 高可用架构

MMM 与 MHA 以及 MGR,高可用架构都有如下的共同点:

  • 对主从复制集群中的 Master 节点进行监控

  • 自动的对 Master 进行迁移,通过 VIP。

  • 重新配置集群中的其它 slave 对新的 Master 进行同步

MMM

需要两个 Master,同一时间只有一个 Master 对外提供服务,可以说是主备模式。


image-20190402160607794

需要基础资源:

资源数量说明主 DB2 用于主备模式的主主复制从 DB0~N 台可以根据需要配置 N 台从服务器 IP 地址 2n+1N 为 MySQL 服务器的数量监控用户 1 用户监控数据库状态的 MySQL 用户(replication)代理用户 1 用于 MMM 代理端改变 read_only 状态

故障转移步骤:

  • Slave 服务器上的操作完成原主上已经复制的日志恢复使用 Change Master 命令配置新主

  • 主服务器上操作设置 read_only 关闭迁移 VIP 到新主服务器

优点:

  • 提供了读写 VIP 的配置,试读写请求都可以达到高可用

  • 工具包相对比较完善,不需要额外的开发脚本

  • 完成故障转移之后可以对 MySQL 集群进行高可用监控

缺点:

  • 故障简单粗暴,容易丢失事务,建议采用半同步复制方式,减少失败的概率

  • 目前 MMM 社区已经缺少维护,不支持基于 GTID 的复制

适用场景:

  • 读写都需要高可用的

  • 基于日志点的复制方式

MHA


image-20190402162734119

需要资源:

资源数量说明主 DB2 用于主备模式的主主复制从 DB2~N 台可以根据需要配置 N 台从服务器 IP 地址 n+2N 为 MySQL 服务器的数量监控用户 1 用户监控数据库状态的 MySQL 用户(replication)复制用户 1 用于配置 MySQL 复制的用户

MHA 采用的是从 slave 中选出 Master,故障转移:

  • 从服务器:选举具有最新更新的 slave 尝试从宕机的 master 中保存二进制日志应用差异的中继日志到其它的 slave 应用从 master 保存的二进制日志提升选举的 slave 为 master 配置其它的 slave 向新的 master 同步

优点:

  • MHA 除了支持日志点的复制还支持 GTID 的方式

  • 同 MMM 相比,MHA 会尝试从旧的 Master 中恢复旧的二进制日志,只是未必每次都能成功。如果希望更少的数据丢失场景,建议使用 MHA 架构。

缺点:

MHA 需要自行开发 VIP 转移脚本。

MHA 只监控 Master 的状态,未监控 Slave 的状态

MGR

MGR 是基于现有的 MySQL 架构实现的复制插件,可以实现多个主对数据进行修改,使用 paxos 协议复制,不同于异步复制的多 Master 复制集群。

支持多主模式,但官方推荐单主模式:

  • 多主模式下,客户端可以随机向 MySQL 节点写入数据

  • 单主模式下,MGR 集群会选出 primary 节点负责写请求,primary 节点与其它节点都可以进行读请求处理.


// 查看MGR的组员select * from performance_schema.replication_group_members;// 查看MGR的状态select * from performance_schema.replication_group_member_stats;// 查看MGR的一些变量show variables like 'group%';// 查看服务器是否只读show variables like 'read_only%';
复制代码

优点:

  • 基本无延迟,延迟比异步的小很多

  • 支持多写模式,但是目前还不是很成熟

  • 数据的强一致性,可以保证数据事务不丢失

缺点:

  • 仅支持 innodb

  • 只能用在 GTID 模式下,且日志格式为 row 格式

适用的业务场景:

  • 对主从延迟比较敏感

  • 希望对对写服务提供高可用,又不想安装第三方软件

  • 数据强一致的场景

读写负载大问题

读负载大:

  • 增加 slave

  • 加中间层(MyCat,ProxySQL,Maxscale)

  • 读写分离

关于写负载大:

  • 分库分表

  • 增加中间层


用户头像

武鹏

关注

还未添加个人签名 2020.04.23 加入

还未添加个人简介

评论

发布
暂无评论
第五周总结