架构-千万流量
微服务架构
服务化好处
-
复用性,消除代码拷贝
-
专注性,防止复杂性扩散
-
解耦合,消除公共库耦合
-
高质量,SQL稳定性有保障
-
易扩展,消除数据库解耦合
-
高效率,调用方研发效率提升
-
潜在问题
-
系统复杂性上升
-
层次间依赖关系变得复杂
-
运维,部署更麻烦
-
监控变得更复杂
-
定位问题更麻烦
-
微服务粒度
-
统一服务层
-
一个子业务一个服务(互联网最佳实践)
-
一个库一个服务
-
一个接口一个服务
高可用(是分布式系统架构设计必须考虑的因素方法论:集群冗余+故障自动转移)
-
“端”到“反向代理”(keeplived+VIP,故障自动转移)
-
“反向代理”到“站点应用"(站点应用的集群冗余,探测存活性,自动流量转移)
-
“站点应用”到“微服务”(微服务客户端的连接池来自动转移,微服务集群冗余)
-
“微服务”到“缓存"(一般没有高可用需求,只需保证数据库不会雪崩)
-
“微服务”到“读库”(冗余,通过数据库的连接池 实现自动转移)
-
“微服务”到“写库"(相互同步,keeplived+VIP,故障自动转移)
高并发(是分布式系统架构设计必须考虑的因素)
-
方法:垂直扩展,水平扩展(无限性能)
-
反向代理层
-
站点应用层
-
微服务层
-
数据层
负载均衡(是分布式系统架构设计必须考虑的因素)
-
反向代理层,站点应用层,微服务层,数据层如何实施负载均衡
-
连接池很重要,高可用/扩展性/负载均衡,都和它相关
-
过载保护不掉底,静态权重,动态权重
-
连接代表服务,分值代表服务(连接)处理能力
-
处理成功加小分,处理失败扣大分
-
临界边界喘小口气
-
死亡状态喘大口气
-
连接池
-
为什么要连接池
- 频繁的建立连接和销毁连接,在吞吐量提升到一定级别的时候会成为性能瓶颈,所以需要提前建立连接,不用每一次都建立和销毁
-
两个核心数据结构
-
连接数组
-
锁数组
-
-
三个核心接口
-
高可用,故障自动转移
-
扩展性,服务发现:自动载入新服务节点配置+动态连接池
-
负载均衡:轮询,随机,静态权重,动态权重
数据库架构
读性能
-
数据库要设计什么?
-
依据“业务模式”设计库表结构
-
依据“访问模式"设计索引结构
-
-
读性能提升,常见方法与实践?
-
增加索引,不用实例不同索引
- 新增索引代表新建b+树,写入数据时会修改b+树,b+树越多,旋转会越多,写性能越低
-
增加从库,使用数据库分组架构
-
增加缓存,注意防止雪崩
-
垂直拆分与高可用
-
尽量把:
-
长度较短
-
访问频率较高
-
经常一起访问的属性放在主表里
-
-
为何要将字段短,访问频率高的属性放到一个表内?
- 原因是:数据库缓冲池,逻辑上,以row为单位缓冲数据
-
高可用
- 冗余+故障自动转移
主从一致性
-
主从数据冗余,主从不一致:
-
忽略
-
强制读主
-
借助缓存,选择性读主
-
-
主主数据冗余,主主不一致:
-
数据库不同初始值,相同增长步长
-
应用层生成不冲突ID
-
一个主库提供服务
-
扩展性
-
扩展性,解决什么问题?
-
底层表结构变更
-
水平扩展,分库个数变化
-
底层存储介质变化
-
-
方案一,停服扩展(离线,非高可用)
-
挂公告,暂停服务
-
离线迁移数据
-
恢复服务
-
-
方案二,pt-online-schema-change(平滑)
-
方案三,追日志方案(平滑)
-
升级服务,记录日志
-
离线迁移数据
-
追日志,补充增量
-
校验数据
-
迁移流量
-
-
方案四,双写方案(平滑)
-
服务升级,“数据修改”双写
-
迁移数据小工具,进行数据迁移
-
数据校验小工具,校验数据一致性
-
切流量到新库,完成平滑迁移;
-
水平切分,秒级成倍扩容
-
互联网大数据量,高吞吐量,高可用微服务分层架构
-
数据库实现秒级平滑扩容的三个步骤为:
-
修改配置(双虚ip,微服务数据库路由)
-
reload配置,实例增倍完成
-
删除冗余数据等收尾工作,数据量减半完成
-
缓存架构
进程内缓存
-
优点
-
节省内网带宽
-
时延更低
-
-
不足:一致性难以保证
-
保证一致性的方法?
-
单节点通知其他节点
-
MQ解耦,通知其他节点
-
放弃实时一致性,定期从后端更新数据
-
-
为什么不能频繁使用进程内缓存?
- 违背了“站点无状态、服务无状态”的设计准则
-
什么场景适用?
-
只读数据
-
并发极高,透传后端压力极大
-
允许一定程度上数据不一致
-
-
再次强调:
-
不要为了炫技,而使用进程内缓存
-
大部分场景,请使用缓存集群(redis/memcache)
-
常见误用与实践
-
服务与服务之间不要通过缓存传递数据
-
如果缓存挂掉,可能导致雪崩,此时要做高可用缓存,或者水平切分
-
调用方不宜再单独使用缓存存储服务底层的数据,容易出现数据不一致,以及反向依赖
-
不同服务,缓存实例要做垂直拆分,不宜共用缓存
架构实践
-
互联网缓存最佳实践:Cache Aside Pattern
-
读实践:先缓存,命中返回,未命中读数据库,再设置缓存
-
写实践:淘汰缓存而不是修改缓存,先操作数据库,而不是先淘汰缓存
一致性
-
数据库主从,何时不一致?写后立即读,短时间内,读旧数据
-
数据库缓存,何时不一致?写后立即读,短时间内,旧数据入缓存
-
优化思路:如果有旧数据入缓存,应该及时把这个旧数据淘汰掉
-
优化方法:
-
二次淘汰法(异步,服务)
-
设定超时时间,有机会修正
-
redis还是mc
-
redis
-
复杂数据结构
-
持久化
-
天然高可用
-
存储内容比较大
-
-
memcache
- 纯KV
-
为什么mc在纯KV能更快呢?
-
预分配内存池
-
redis的VM机制更慢
-
redis的CPU计算复杂
-
多线程可利用多核
-
-
其他:
-
redis源码可读性好
-
redis和mc都需要手动水平切分
-