06知识点
2019-04-07 本文已影响0人
Fix12138
数据库技术演进之路
- RDBMS(单机关系型):Oracle、MySQL
- NoSQL(分布式非关系型):MongoDB、HBase、Hive、ES
- NewSQL(分布式关系型):Google Spanner/F1、TiDB
NewSQL具备NoSQL扩展性,有具有传统关系型数据库ACID特性的分布式关系型数据库
传统关系型数据库分表实践
分库:用户库、商品库、交易库
分表:uid%1024
MySQL Scale Out
- 架构升级:
- 简单主从架构->按DB拆分的架构
- 无缓存->有缓存
- 硬件升级:
- 机械硬盘->SSD(SSD应用接口不用,传输速度也不同,如SAS接口、PCIE接口等)
- 存在问题:
- 跨数据库事务(只能通过分布式事务解决)
MySQL读写分离
- 架构继续升级:
- 表拆分(分表)
- 读写分离(应用层)
- 存在问题:
- 读写分离应用层实现
- 非Partition Key读写问题
MySQL Sharding
- 架构继续升级:
- 解决写入横向扩展(数据库容量问题)
- 垂直拆分:分库
- 垂直拆分:分表
- Sharding组件:Sharding-JDBC(Sphere)github地址
- 存在问题:
- 业务Partition Key选择
- 业务多维度查询
- 数据同步(同步异步)
- Sharding语义如果透明
- 机器资源使用率低
MySQL DB Proxy
- Sharding结构升级:
- 组件->单独进程:百度DbProxy
- 存在问题:
- 链路过长
- 语言限制
Sharding
引发的问题(MySQL Proxy和DB Proxy代价)
- 应用限制
- 业务妥协
- 架构成本
- 资源成本
使用NewSQL可以解决这些问题
分库
库的共享:大部分场景下读请求量远大于写请求量,但写请求重要性又高于读请求。为了避免读请求对写请求的影响,将读API和写API拆分成两个微服务,但底层共享同一个库
DB进程共享:一个MySQL里面好多库。
分表
MySQL数据量达到何时分表,与每行的数据量有关:
- sizeof(row)小于100字节,5千万一张表
- sizeof(row)大于等于100字节,1千万一张表
Partition Key的选择:
- 每个表内的数据量尽量均匀
- 业务查询需求字段
- 数据热度分布(当按照时间月份分表的时候会导致负载不均衡)
如何解决分表好多个字段查询?
比如一个行有两个字段uid和infoid
基因法:当uid是固定的,infoid是动态的,可以将uid和infoid的低4位在生成的时候保证一直,这样就可以都分到同一个表中。
当uid和infoid都是固定的,这样只能先按照uid分表,再建一张按infoid分表的映射表。
分库分表一定要结合业务需求来设计,如果没有业务需求无法设计合理的分库分表
比如有按照时间范围的搜索需求,就不应该用MySQL来解决,应该用搜索引擎比如ES来解决。
常用的数据库中间件组合:
ORM:MyBatis 3
Sharding: Sharding-JDBC/Sphere
Merge:result merge
DataBase Connection Pool:DBCP(apache)
传统关系型数据库高可用方案
平台架构:
- WEB
- API
- 管理数据库
- 检查与故障切换
- 数据库集群
- 运行主机环境
主从切换:
提供虚IP,可以采用nginx、LVS等负载均衡,或者keepalive等工具。
整个高可用方案称作MHA
NoSQL数据库应用实践
MongoDB面向文档的NoSQL数据库
特性:
- 可扩展
- 高性能
- 开源
- C++编写
- 面向文档
- 支持全文索引
- 备份和高可用
- 自动分片
- 丰富查询能力
- Map/Reduce
- GridFS存储二进制文件
MongoDB副本集(replica Set)
- 数据多份冗余
- 跨交换机部署
- 更快的选举方式(参考raft分布式协议)
支持的分片方案
- Sharding Range-based
- Sharding Hash-based
应用场景
- 基于位置的移动搜索应用(基于自身的地理空间索引)LBS
- 日志分析平台(MongoDB本身自带的高性能聚合框架)
- 存储简历、或者投递关系等相对复杂的数据结构,比如简历库
- 存储用户数据,或者帖子信息,比如用户中心
- 非交易相关的基本都可以用
文档设计
- 文档设计经验:尽量不要让数据成为查询条件,统一大小写,字段尽可能小,上层做映射
- _id选择:根据业务选,默认ID生成规则类似Snowflake,12个字节,存储空加大,有服务端开销
- _id生成:尽量在客户端生成,减少服务端的压力
- 减少key的字符大小,代码层可以用宏定义的方式保证可读性
Schema设计
- 优先考虑内嵌
- 如果要单独访问一个对象,那么他就不适合内嵌到其他对象中
- 数组不应该无限制增长
- 反范式设计时需要谨慎
锁机制
Mongo 2.6之前悲观锁,在内存中对数据结构修改时加锁
Mongo 3.0WT(存储引擎WiredTiger),MVCC机制,乐观锁lock-free并发控制
压缩算法
- Snappy:原始数据每满32KB就进行压缩然后写到磁盘
- Zlib:来的原始数据直接压缩,压缩后的数据满32KB则落盘
遇到问题
- 大量删除数据(类似MySQL大量删除)
- 大量数据空洞(碎片),大量的空间碎片无法使用,空洞数据也会加载到内存,导致有效负荷低
- 删除从库,重新同步,切换成主库,具体操作步骤