数据库架构选型与落地,看这篇就够了
0x1
数据库架构有哪些
IO瓶颈:大规模的用户查询和写入,由于单机数据库的IO有限无法支撑; 存储瓶颈:大量数据的存储让数据库原有的逻辑结构已经无法适用,性能急剧下降; 可用性:重点业务系统对数据库的要求是不间断地提供服务,一旦遇到突发事件时系统可以快速恢复; 安全性:数据的容灾能力,保证数据在任何时候不会丢失(避免运维删库跑路);
结构简单,技术成熟,市面上大多数数据库都支持这个方案; 业务入侵最低; 数据拥有多个容灾副本,提高数据安全性; 当主服务器故障时,可立即切换到其他服务器,提高系统可用性;
无法支持大量写的场景,因为主库无法水平扩展; 从库的数据都是全量并且重复的,浪费存储空间; 数据一致性问题; 数据同步延迟问题;
业务清晰,专库专用,契合服务化的拆分; 冷热数据分离,业务数据相互独立各不干扰; 独立的数据库便于日常迭代和维护;
数据之间无法联表,只能在程序中多次查询组合或者冗余数据; 需要解决分布式事务问题;
单表数据量减少,性能得到提升; 数据都在同个数据库中,没有跨库事务问题;
需要解决跨片查询问题; 数据分片在扩容时需要迁移; 存在IO瓶颈,无法处理大量业务请求;
单表数据量减少,性能得到提升; 数据分散在多个服务器,提高了整体系统的负载能力;
需要解决跨片查询问题; 数据分片在扩容时需要迁移; 需要处理广播表(公共表)问题; 需要解决分布式事务问题;
天然便于水平扩展,后期想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移; 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。
热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁地读写,而有些分片存储的历史数据,则很少被查询。
数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。
后期分片集群扩容时,需要迁移旧的数据,容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带用户id时,将会导致无法定位数据库,从而需要同时向所有库发起查询,再在内存中合并数据,取最小集返回给应用,分库反而成为拖累。
0x2
数据库的选型与落地
无需额外部署,只要和应用绑定一起发布即可; 任意数据库都可以使用;
不能跨语言,比如Java写的sharding-jdbc显然不能用在C#项目中; 数据库连接数消耗高(各个应用节点的连接池不共享);
跨语言,任何编程语言都可以使用; 数据库连接数消耗低(连接池由代理层持有,所以可以复用);
只支持少量数据库(MYSQL/PostgreSQL); 需要单独部署,形成中心化架构(一旦宕机系统将不可用); 多了一层代理层,性能下降;
ShardingSphere
数据分片 分库 & 分表 读写分离 分片策略定制化 无中心化分布式主键 分布式事务 标准化事务接口 XA强一致事务 柔性事务
适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。
应用案例
简单粗暴的UUID:生成足够简单,本地生成无网络消耗,具有唯一性。缺点:无序、无业务意义、过长 基于Redis模式:利用redis的 incr命令实现ID的原子性自增。缺点:需要开启持久化,有可能丢失 雪花算法:Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。 美团leaf:提供雪花和程序自增方案,其中雪花依赖ZK,程序自增依赖数据库。
索引表法:建立索引表,存储用户id和企业id的关系。查询时先通过索引表找到对应用户id之后,再查询数据库。缺点:多一次数据库查询,性能下降。用户和企业关系变动时,需要维护数据。 基因法:截取用户id的部分数据加入到企业id,例如用户id后3位直接加到企业id中,然后分片时根据用户id后3位计算分片,这个时候使用企业id也可以提取这三位数来计算分片位置,缺点是,只能针对单一字段,并且对数据有一定的入侵干扰。 宽表法:使用NOSQL建立宽表(全量表),提供对应的查询能力。异构下的读写分离,缺点是,引入中间件成本、数据一致性问题,数据延迟问题;
0x3
总结一下
数据库架构可以分为主从架构、垂直架构、水平架构,分别解决高可用、密集IO、大规模数据存储问题。 每个架构会面临不同的难题,数据延迟、分布式事务、跨片查询、扩容等等,越复杂的架构面对的难题越多,而我们应该把这些难题考虑进去。 对于架构的选择上,架构不是越复杂越好,应用在不同的阶段需要针对问题点选择合适的架构。 从技术种类上看,实现分库分表技术的中间件分为JDBC方案和PROXY方案。JDBC性能高,跨数据库;PROXY省连接,跨语言。 ShardingSphere是一个功能强大的中间件,支持多种方案(JDBC、PROXY、混合),可以快速实现数据库读写分离、数据库分片等技术方案。 根据业务的特点可以选择不同的分库方案,在复杂的数据库架构中,需要解决分布式事务、分布式id、跨片查询、分片扩容等等问题。
EOF
本文编辑:Jensen
专注分享程序员日常/架构技术/职场干货
八年Java老兵,小米主题设计师,手机输入法设计师,ProcessOn特邀讲师
曾涉猎航空、电信、IoT、垂直电商产品研发,现就职于某知名电商企业
个人微信:Jensvn,交个朋友,一起成长,Java Goals:架构师