多案例分析,从垂直拆分和水平拆分谈谈架构本质问题
前言
架构有很多中,大数据架构,微服务架构,秒杀架构,butong数据库分库分表,读写分离等,他们有哪些共性的东西?
本文从垂直拆分和水平拆分角度,专注谈谈架构共性的东西,提高大家以不变应万变的能力
一、架构的本质
架构设计的本质,是解决耦合性问题,解决耦合性问题的方法是,进行解耦,如何解耦,通过拆分,怎么拆? 垂直拆分和水平拆分,简称横拆和纵拆。不同的架构,本质是进行水平拆分和垂直拆分,简称横拆和纵拆。
后面的篇幅基于不同的架构谈谈什么是怎么进行横拆和纵拆。
二、横拆纵拆案例
1.大数据数据仓库架构
数仓:一般分为原始日志层ODS层,数据仓库层(DWD+DWT+DIM) , 数据集市层(ADS层)。
如何横拆? 从请求层面,进行横向拆分,用户访问ADS层获取到数据,立即返回,不会访问再底层的数据。
如何纵拆? 从业务领域进行垂直拆分,不同的主题表,就是垂直拆分的结果。
上图:来自奈学的文档
2.微服务架构
微服务存在意义: 需要从微服务诞生讲起
微服务诞生前,是一个单体架构,服务层只有一个,DB只有一个,代码都在一个工程里面。随着功能增多、代码复杂度增大、团队内部功能修改影响整个项目,数据库使用率变大,单体架构落后的产能和降本增效的要求形成巨大的矛盾,于是微服务就诞生了。
微服务做哪些事情?
垂直拆分:按照业务领域进行垂直拆分。把一个系统拆成多个系统,例如电商系统,拆为会员系统、订单系统、积分系统、仓库系统、调度系统等,各个系统的数据库都是独立的,顺便把DB做了垂直拆分,做了分库。
水平拆分:原先一个服务,改为多个服务,做复杂均衡,请求打散到多个服务
3.分库分表
如何垂直拆分? 按业务功能垂直拆分,一个表一个库。
如何水平拆分? 一个表拆成多个表就是水平拆分。例如安装userId, 订单id 把数据打散。
4.冷热分离
为什么会有冷热分离的架构设计? 案例:订单系统,每天1000w笔数据,不考虑增量,一年36.5亿数据。系统跑着跑着,性能就会变慢。当然可以使用分库分表架构,如果不拆用分库分表,怎么解决性能问题?
出现性能问题的原因是数据变多,数据少是没有问题,是否可以把这个表的数据变少?例如维持在1亿条数据?怎样才能做到?例如只保留10天的数据,10天前的数据怎么办?问题转移,放到别的层次处理,例如放到历史库,或者大数据集群架构,对实时架构,只保留10天的数据。
总结,冷热分离,本质,是对数据做垂直拆分。如何拆分? 按照热数据和冷数据进行拆分,拆分后,提高热数据的性能。具体在不同的公司,有实时库、实时库查近期的数据、历史库查过去几个月的数据等
5.ES索引性能优化,冷热分离设计
es索引分片问题: es一开始做5个shard数据越来越大,型能越来越慢。怎么办?一开始设计10个shard? 100个shard? 久了还是有性能问题。怎么办?
性能慢的根源:虽然按照分片做了垂直拆分,但每个分片还是有瓶颈。
按照官网建议,一个分片不超过30G数据。单分片达到一定数据量就是会有性能问题,有性能问题再扩容?这是个好解决方案吗?
更优雅的方案:按月建索引,每月一个索引。 分片动态扩容,零成本扩容,让每个分片的数据足够小,同时实现冷热数据分离。每月一个索引,随着数据量变大,新的月份可以增大索引,老数据不变。
优雅方案案例:
写数据: 不同月份的数据写到相应月份。 order_202101, order_202102, order202103 等
读数据:使用order_* 匹配,es支持alias 只要是order开头的可以全部匹配。
客户端限制:限制客户端查询带上时间范围: 月份范围。大部分查询只查近几个月的数据,例如银行APP查流水,可选查1个月内,3个月,6个月,1年的数据。
冷数据生命周期管理:直接把1年前的索引数据删了,一条命令搞定,没有跟es的各种交互。
6. 电商读写分离架构
电商数据:架构都读写放一起,电商数据、互联网数据大部分读多写少,读多写少,为了提高读写性能,进行读写分离。
如何垂直拆分?读写分离本质就是做了垂直拆分,按照读和写进行拆分。
如何水平拆分?
1.对读请求:从请求层面进行水平拆分。CDN->nginx->redis->jvm cache->db 进行四级缓存架构。 CDN存纯碎的静态数据(图片、CSS、js等) , nginx、redis存储动态的数据例如库存、价格、商品详情信息等。越上层抗并发读越多,到DB层,已经没什么压力。
7. 秒杀架构
- 业务初期,没什么并发。
2.业务并发大,目前,一般使用队列解耦,实现削峰填谷的作用。
架构多了两个东西,一个是redis,一个是MQ。redis分担db的读请求,MQ分担DB写请求, MQ性能好的本质,是把DB的随机读写,改为顺序读写,例如KAFKA,ROCKETMQ。
架构升级的本质:就是DB耦合了写和读请求,解决方法是,进行拆分,如何拆分?把写和读交给更擅长写和读的组件去做,把DB的功能向上一层移动,转移到服务层去处理。
总结
解决问题的思路:不管什么数据,变大了,都有性能问题,出现性能问题的原因是,数据变大了,按照目前的方案,只能解决小数据的问题,又不想引入复杂的架构,如何处理? 处理思路是: 1.大问题处理不了,只能处理小问题,那能不能把大问题转化为小问题? 分而治之的思想。hadoop的map reduce不也是这个思路?学习的思想:本身做不了的事情,放到外面做,本层做不了是事情,放到上层做。有同学问,难道不能扩大自身的能力?答:可以,例如db,扩大能力,就变成分库分表,就是分库分表还是有读写性能啊。本文专注在分层架构设计思想,不要跑题哦。。。
总结:看不同的架构,先看看架构本质,耦合了哪些问题,它的解决方案,做了哪些拆分