数据库发展史
RDBMS
代表:oracle(商业),mysql(开源)。
关系型数据库 (RDBMS) 是当前应用最广泛的数据库管理系统,不仅可以存储数据,还可以进行复杂的数据运算(left join,子查询等)。
他存在着如下几个不足:
- 不能处理非结构化的数据。
- 本质上还是单机系统,很难满足海量数据的需求,要做分库分表。
- 可扩展性比较低。
NoSQL
NoSQL = not only SQL,分布式非关系型数据库,相比于RDBMS主要优势如下:
- 可以处理非结构化的数据
- 低延迟的读写速度
- 高性能和扩扩展性(牺牲了ACID事务)
NoSQL数据可以大致分为4种类型:
- 键值型数据库,比如Redis、Memcached等
- 文档型数据库,比如MongoDB等
- 列存储数据库,比如HBase,Cassandra等
- 图数据库:Neo4J等。
NewSQL
NoSQL虽然解决了RDBMS一些问题,但是并不能完全取代RDBMS,比如不能用sql查询数据,所以RDBMS还是无法满足性能问题,虽然可以通过分库分表,但是还是有一定的复杂性。
NewSQL = RDBMS + NoSQL,分布式关系型数据库,既满足线性扩展性,又能处理分布式事务,比如TiDB。
RDBMS架构演进
主从
所有业务放一个库,并做主从(通过binlog同步)。应用层的读写分离可以用第三方应用比如mycat、ShardingSphere,这两个也支持分库分表。
垂直拆分
分库,把商品、用户、订单拆出来,减少IO的竞争,而且连接数支持更多。
如果一个表的字段太长,也可以垂直拆分,把不常用的拆到新的表中,需要的时候再做表关联。比如原table的字段有(col1,col2,col3...col10),拆分后变成table(col1,col2,col3,col4,col5),table_ext(col6,col7,col8,col9,col10)。
水平拆分:
单个分片
分表,比如拆分4个,对4取模,用户表的partition key是userid,就是userId % 4。比如id为1的,在user1读写,id为6的,在user2读写。
partition key是怎么选择的呢?
- 根据用户城市选择,这样会造成某个库的数据比较多
- 根据注册时间,也会不均匀
- 要选随机的,这样hash的时候,每个库都比较均匀。
多个分片
上面的例子,只有一个字段是partition key,如果是多个,比如既可以按照id查询,又可以按照uname查询,怎么办?如果只有一个partition key,为id,那查询name的时候,只能全库搜索了,这样性能就很低了。
基因法(假设模16):
- username取后4位
- id生成60位
- 把username的后4位加到id后面
这样查找的时候,不管是对id查找,还是对username查找,都可以直接根据后四位进行查找。
上面的id,是根据username生成的,如果id是固定的,不依赖username生成的,要怎么办呢?
映射法:
- 建立username和id的映射表(这个必须是1对1 ,如果是1对多,依然要去多个库查找,这样还是很耗性能)
- 查询usename的时候,先去映射表查找对应关系,获取id
- 通过id取模的方式,去相应的库里查找
分库分表问题
- 分库分表后,sql聚合、join、子查询限制。
- 再次分表的成本高,已经分成4个表了,再分个8表?
- 恢复成本高,需要对多个已拆分的库、表恢复
- 运维成本高,需要多多个已拆分的库、表维护
- 数据一致性如何解决?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。