架构师训练营 第 5 课学习总结
学习了分布式缓存的使用场景,及一致性Hash解决缓存的负载不均衡问题;使用消息队列实现异步流程,还有负载均衡的原理,Mysql复制。
分布式缓存使用场景
适用于一写多读,且读失败可以溯源获取不影响业务的场景。常见的方案有memcached, redis,前者没有实例间的通信,各自单独负责存储和响应,靠调用端使用缓存Hash映射到对应的实例;后者实现了实例间的通信,所有实例构成分布式系统,系统将缓存分布到固定数量的桶上,所有实现都存储了这个映射信息,所以调用落到任何实例,都知道要去哪个实例获取缓存值,不需要调用端做Hash逻辑。
有时候缓存会被拿来当存储使用,这会增加系统复杂度,最佳实践是缓存就当缓存用。
缓存是性能优化的大杀器:技术简单,性能优化显著,应用场景多。需要认真对待。
一致性Hash
为了解决原始的取模Hash导致的缓存不均衡、加实例导致缓存命中率低的问题,提出了一致性Hash解决方案。它将实例映射到固定数值范围的环上,缓存数据读写时,用生成Hash顺时针找到实例节点。在增减实例时,只会影响实例附近的缓存,不会生成全局的缓存迁移,导致大面积缓存失效的问题。为了解决缓存不均衡,通常需要使用虚拟节点,即将实例节点当成若干个虚拟节点,均匀分布在Hash环上,这样能保证在加实例后,能够尽量分担到集群中各个实例节点的缓存负载压力。
消息队列实现异步流程
从前面的学习中了解到异步能提高系统的并发处理能力,核心思想是避免高速模块同步等待低速模块的处理,从而充分利用前者的性能优点。消息队列构建起了两者的数据交互桥梁。数据库经常是系统中并发性能的短板,为了解决该问题,在数据库调用者与数据库之前放置消息队列,系统收到调用后,将数据放入消息队列,然后立即响应调用者,之后消费费从消息队列取出数据,以数据库能接收的并发进行写操作,如果需要的话在完成后再通知调用者。当然消息队列也有不适用的场景,比如事务的处理、需要通过数据库校验才能真正知道如何响应调用者的场景。
负载均衡
Http重定向负载均衡:工作在网络模型第7层的应用层,主要使用http协议,需要调用端发请求到负载均衡,拿到需要请求的地址,再请求该地址;缺点是需要多次请求,浪费流量,增加耗时;
DNS负载均衡:调用端从DNS服务器上拿到请求的地址,请求该地址,这个过程并不需要像Http重定向那样多一次发请求,因为DNS是每次请求都需要的操作,但有缺点是DNS有多级的缓存,当负载均衡下的机器需要更新时,调用端不能及时得到最新可用的地址;
以上两种都有安全性问题,即暴露业务机器,因为业务机器通常有比较多端口和程序,安全隐患会比单独的负载均衡机器要多。
反向代理负载均衡:工作在第7层的应用层,使用http协议,由于http需要等待及处理底层协议包数据,然后再发往业务机器,响应时也需要封装好http包,这时候负载均衡的处理能力会成为瓶颈,导致它所有负载的机器数量有限,只适用于小型系统中(通常10多台业务机器);
IP负载均衡:工作在网络模型第3层的ip层,主要使用ip协议,负载均衡机器收到ip包后,修改源地址为自身,目标地址为业务机器ip,然后业务机器处理完成后,将数据响应给负载均衡机器(因为IP包的源地址已经为负载均衡机器IP),负载均衡机器收到后,将其响应给客户端。相对于反向代理负载均衡,IP负载均衡处理的是IP包,需要的计算少很多,也不需要进行http的封装等,所以能承受更多的调用压力;
数据链路层负载均衡:工作在第2层的数据链路层,首先将负载均衡机器与下游机器共享一个虚拟IP,数据经负载均衡机器时,修改MAC地址,下游各台机器都会收到数据,但只有MAC地址一致的才会处理数据,由于机器都共享一个虚拟IP,所以最终可以由接收数据的下游机器直接响应给客户,不用经过负载均衡机器。主要解决了IP负载均衡机器的流量压力,因为响应数据都经过负载均衡的话,它的网卡带宽会成为瓶颈,但IP层因为TCP协议的限制,只能通过修改源地址和目标地址,再通过负载均衡中转响应数据的流量,所以大型的系统具有大流量的场景,一般使用数据链路层负载均衡。
Linux内置的LVS支持数据链路、IP负载均衡,应用十分广泛。
大型系统会使用多个负载均衡,组成多层负载均衡,如最外层是DNS负载均衡,再是数据链路层,然后内部通信还可以是反向代理。
Mysql复制
主从复制:主节点提供写操作,从节点提供只读操作,为系统作数据备份,读压力的负载均摊;
主主复制:解决主节点宕机导致服务不可用,平时只有一个主节点提供写能力,另一主节点备份数据,前者宕机时,后者及时顶上,防止系统不可用,提高系统可用性。主主切换时,会有一段不可用时间,且会有数据丢失的风险,但这是不可避免的。
评论