架构师训练营 05 周 -- 学习总结
分布式缓存的架构:架构原理和使用中的注意事项
无处不在的缓存:
CPU 缓存、操作系统缓存、数据库缓存、JVM 编译缓存
CDN 缓存、代理与反向代理缓存、前端缓存、应用程序缓存、分布式对象缓存
缓存数据存储-hash表
查询的时间复杂度是O(1)
通过表的起始地址和偏移量来计算key在表中的位置
偏移量通过key的hashcode来计算,得出一个4字节的正整数,用这个hashcode对表的长度取模,得出数组下标,计算出偏移量(数组下标*表中数据项的长度)。
缓存的关键指标:
缓存命中率 -- 多少次重用同一个缓存响应业务请求。是衡量缓存是否有效的指标
影响缓存命中率的因素
缓存键集合大小:减少可能的缓存键的数量。缓存键越少,被重用的可能性越高
缓存可使用的内存大小:决定了缓存对象的平均大小和数量。物理上缓存的对象越多,命中率越高
缓存对象生存时间(TTL, time to live):根据业务需求设置TTL。对象缓存时间越长,被重用的可能性越高
分布式缓存的架构:常见的缓存实现形式
通读缓存(read-through):代理真正的数据源,客户不会感知真正的数据源。直接返回缓存数据,并在请求未命中缓存的时候,获取真实数据。
a. 代理缓存:代理服务器代理用户上网,缓存网页内容
b. 反向代理缓存:代理数据中心的所有服务器。缓存未命中,转发请求
c. 多层反向代理缓存:多级缓存
d. 内容分发网络(CDN):缓存静态内容,动态内容仍然分发给服务器处理。但是不同网络运营商的不同地区的机房,都必须部署CDN为用户提供服务。
目前的云服务提供了CDN服务,同时配置静态文件和动态内容。
旁路缓存(cache-aside):客户端或者应用代码知道缓存和真正的数据源,缓存的更新由客户端或应用程序代码实现。
a. 浏览器对象缓存:javascript实现
b. 本地对象缓存:对象缓存在应用程序内存中、共享内存、本地的缓存服务器进程中。比如,jboss缓存集群
c. 远程分布式对象缓存:独立的缓存服务器集群。比如, Memcached
分布式缓存架构:一致性Hash算法
余数hash的问题:服务器扩容的时候,会有一部分缓存不会命中
一致性hash算法:
优点:扩容的时候,只有少部分的缓存数据需要移动到新的节点上。
缺点:如果服务器节点在hash环上的位置不均匀,会导致服务器上的缓存不均衡。
基于虚拟节点的一致性hash算法
实际使用中,每个实际服务器节点,虚拟成150个或者200个虚拟节点放到环上。
这会使得服务器的虚拟节点在环上的位置分布尽量均衡,使得每个服务器节点负载尽量平衡。
各种介质数据访问延迟
技术栈各个层次的缓存:尽量前置缓存数据
缓存是系统读性能优化的大杀器,但是,写数据性能无法优化
不适合使用缓存的数据
频繁修改的数据:一般来说,读写比2:1以上的数据(写一次,被读两次),才值得缓存
没有热点的访问:如果数据访问没有遵循二八原则(大部分的数据访问没有集中在小部分数据集上),很少被访问的数据会很快被挤出缓存,这样缓存数据是没有意义的。
缓存使用的注意事项:
数据不一致和脏读。需要设置缓存失效时间,因此,需要系统容忍一定时间的数据不一致。另一种策略是,数据更新时立即更新缓存(使缓存数据立刻过期,或者立刻删除,迫使用户访问时,去读取数据库,然后更新缓存)
缓存雪崩:缓存服务器全面崩溃时,导致数据库服务器访问压力过大而崩溃。
缓存预热:缓存服务器启动的时候,预加载热点数据
缓存穿透:高并发访问一个不存在的数据,请求最终会落到数据库上,会造成数据库压力过大。对策是,需要将不存在的数据也缓存起来(value是null),同时设置一个较短的失效时间。
消息队列
同步调用vs.异步调用
消息队列
点对点模型:消息只被消费一次
发布订阅模型:一次生产多次消费
异步调用的优点
提升处理性能
更好的前后端的伸缩性
更容易实现削峰填谷
失败隔离和自我修复:生产者和消费者互相不受对方失败的影响
解耦:发布者和消费者不需要相互知道,可以各自独立开发
事件驱动架构EDA
主要的MQ产品
RocketMQ
ActiveMQ
RobbitMQ
Kafka:社区活跃度高
负载均衡架构
如何做请求转发
a. HTTP重定向负载均衡:很少使用
两次http请求,性能低
安全性差
b. DNS负载均衡
域名解析的结果会缓存在客户端,不用每次请求都做DNS解析
解析出来的IP地址,是数据中心内的负载均衡服务器的IP地址,再由这个负载均衡服务器分发到实际的应用服务器中
c. 反向代理负载均衡
通常应用在比较小的集群中
效率低,性能差,因为反向代理需要等待所有的tcp包到达,才能构建完整的http协议包,然后转发http请求;同时响应处理也是类似的。
大型互联网应用很少使用
d. IP负载均衡:
负载均衡直接修改TCP/IP数据包中的源IP地址(改为自己的IP地址)和目标IP地址(改为应用服务器IP地址)
用户收到TCP/IP数据包后自己构建HTTP响应,展示页面
但是,响应的数据量大,所以TCP/IP包会很多,这增加了负载均衡服务器的压力。
e. 数据链路层负载均衡
负载均衡服务器和应用服务器使用了同一个虚拟IP地址
负载均衡服务器修改链路层中数据包中的MAC地址(用应用服务器的MAC地址,替换掉自己的MAC地址)
因为请求的数据包中的源地址是用户的IP地址,所以在响应数据包中,将请求的源地址变成目标地址,响应可以直接返回用户
大型互联网应用中经常使用,效率高,性能好。
负载均衡算法
轮询
加权轮询
随机,加权随机
最少连接
源地址散列:同一个IP的请求总在同一个应用服务器上处理,实现会话粘滞。
集群环境中的session管理
a. Session 复制:
应用服务器之间相互复制session
Session 数据量大时,每个服务器压力大,性能差,不利于应用的伸缩。
b. session绑定
同一个IP请求总到同一台服务器上
应用服务器宕机的时候,session信息丢失,用户体验差
c. 利用cookie记录session
cookie大小有限
有些浏览器禁用cookie
虽然有限制,但实践中也比较常用
d. session服务器
共享的session服务器,每个应用服务器都可以拿到完整的session信息
应用服务器是无状态的服务器,sharing nothing分布式架构
互联网应用中最常用的方式
版权声明: 本文为 InfoQ 作者【骏马】的原创文章。
原文链接:【http://xie.infoq.cn/article/7338a09f97db7c1386c3c7974】。未经作者许可,禁止转载。
评论