基础认知
传统关系型数据库(一般,指 InnoDB MySQL )参考指标:
- 1TB:如果数据库会膨胀到 TB 级别,需要考虑 MySQL 分库分库。
- 1000 万行或 10GB:单表的记录数超过 1000 万行,或单表磁盘空间占用超过 10GB,需要考虑分表
- 每秒 1000 次写入:单节点写入速率超过每秒 1000 次。可以考虑根据业务场景引入 Redis 或消息队列作为写缓冲,实现数据库写操作异步化
来源:刘春辉 《Shopee 是如何进行数据库选型的?》
数据库的单机QPS不过几千,显然满足不了互联网业务场景下对高并发的要求。因此,分库分表 + 读写分离成为常态。
- 分库,即把一个库分成多个库,部署在多个实例之上。
- 读写分析:主库承载写请求,从库承载读请求。由于多数业务场景都是读远多于写,一个主库挂多个从库,可以有效降低对单库的压力。
如果写请求继续增加(或,数据量增加)达到瓶颈,就继续分库分表;反之,如果读的请求上升就挂更多的从库。
分表复杂性
然而线上业务情况往往复杂的多,随着数据量增加、用户量增加,数据库分表(分库,一般按照业务因此问题不大,暂且不表)会逐渐暴漏出以下问题:
分片复杂
容量预估困难
- 某单一数据没有考虑分表,随着业务发展需要分表,且分表字段不是已有的ID字段,变更代价高昂
十倍架构设计、百倍数据设计
Coordinate&Integrity
- 以订单为例,业务会按照买家、卖家、订单状态、支付方式等维度筛选数据。若以买家维度分库分表,则卖家维度的查询会变得困难;反之亦然。解决方案一般是以主要查询为维度,分别建立异构索引,不同数据必然存在一致性的难题
数据倾斜
- 诸如点赞和关注等偏社交类业务数据,按照用户维度分库分表后常出现数据分布不均匀的现象,少数分片的数据量可能远大于其他分片;这些大分片往往也是读写的热点,进而容易成为性能瓶颈。
解决方案:使用大素数取模再分表 可以得到较好的效果
查询复杂
- 多分表查询
- 多维度维度:见订单部分
存储细分
由于数据分表可见的复杂性,在实际使用中,随着对分表的疲劳,不同于诸多传统关系型数据库的新兴分布式数据库也越来越多的被使用在生产环境,例如:TiDB
无论数据库如何多变,了解其类型和原理,才能看穿表象,把握本质,更好的应用到业务的设计之中
按照应用类型来分
- 键值型:ID - Value
- 表格型:ID Collection + Time - Value
- 关系模型: ID + ID Collection + Time - Value
参考: 认识资源
按照存储模型来分
- B-tree:读取友好,数据有序。LIRS算法,将缓冲池分为两级,数据首先进入第一级,如果数据在较短的时间内被访问两次或者以上,则成为热点数据进入第二级,每一级内部还是采用LRU替换算法
- Bitcask:写入友好,数据无序。在内存中存储了主键和value的索引信息,磁盘文件中存储了主键和value的实际内容。需要定期执行合并(Compaction)操作以实现垃圾回收。Bitcask通过索引文件(hint file)来提高重建哈希表的速度
- LSM:写入友好,数据有序。将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘,读取时需要合并磁盘中的历史数据和内存中最近的修改操作,需要定期执行合并(Compaction)操作以实现垃圾回收
本文作者 : cyningsun
本文地址 : https://www.cyningsun.com/08-18-2020/first-lesson-of-database.html
版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!