数据库基本概念

结构化数据、非结构化数据、半结构化数据
  1. 结构化数据
  • 是由二维表结构来逻辑表达和实现的数据,严格遵循数据格式和长度规范,也称为行数据
  • 特点:数据以行为单位,一行数据表示一个实体的信息,每一行数据的属性是相同的
  1. 非结构化数据
  • 是指数据结构不规则或者不完整,没有任何预定义的数据模型,不方便用二维逻辑表来表现得数据(word文档、图片、视频音频等)
  1. 半结构化数据
  • 介于结构化数据与非结构化数据的一种,虽然没有严格意义上的数据模型结构,但是包含相关标记,可以用来对记录和字段进行分层,常见的有XML,JSON等数据形式
数据库的ACID特性
  • Atomic 原子性
  • 一个事务的操作,要么全部完成,要么全部不完成,不会结束在中间的某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态。
  • Consistency 一致性
  • 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • Isolation 隔离性
  • 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)
  • Durability 持久性
  • 事务处理结束后,对数据的修改是永久的,即便系统故障也不会丢失。
关系型数据库的建构演进

结构化数据HDFS dataframe 结构化数据库_服务器

  • 阶段一:一个应用服务器配一个关系型数据库,每次读写数据库
  • 阶段二:使用一般的关系型数据库,数据首先不会称为性能瓶颈,通常是一台服务器无法承载流量的压力,并且只使用一台服务器会产生单点故障的问题。因此这个阶段一般会增加服务器并且在流量入口使用Nginx做一层负载均衡,保证每个服务器上流量均匀,但此时仍然是读写同一个DB
  • 阶段三:规模继续扩大,达到了数据库的性能瓶颈,此时会进行读写分离,即每次写主DB,读从DB,并且可以配备多台从服务器,保证主从服务器的同步,相当于在读方面提供了水平的可扩展性
  • 阶段四:规模更加扩大,即使做了读写分离,对于主DB压力越来越大,因此就进行“分库分表”策略,对表进行垂直拆分,对库进行水平扩充。
    以一定的单号(例如交易单号),以一定的规则(例如取模),交易单号对2取模为0的丢到数据库1去,交易单号对2取模为1的丢到数据库2去,通过这样的方式将写数据库的流量均分到两台数据库上。
    一般分库分表会使用Shard的方式,通过一个中间件,便于连接管理、数据监控且客户端无需感知数据库ip
关系型数据库的优缺点
  • 优点
  • 易理解:二维逻辑表结构易理解
  • 操作方便
  • 数据一致性
  • 数据稳定:数据持久化到磁盘,没有丢失的风险
  • 服务稳定:关系型数据库服务器性能稳定,很少宕机异常
  • 缺点
  • 高并发下IO压力大,即使只针对一行中的某一列进行计算,也会将整行数据从存储
  • 为维护索引付出的代价大:1、创建、维护索引耗时,2、索引需要占用物理空间,3、对表进行增删改查的时候也要董涛维护索引
  • 维护数据一致性付出的代价大
  • 水平扩展后问题难处理:跨库的join操作,分布式事务处理没有好的解决方案
  • 表结构扩展不方便:表结构schema是固定的,如果需要修改表结构,需要执行DDL(data definition language)语句修改,修改期间会导致锁表,部分服务不可用
  • 全文搜索功能弱

总的来说,关系型数据库在高并发下的能力是有瓶颈的,尤其是写入/更新频繁的情况下,出现瓶颈的结果就是数据库CPU高、Sql执行慢、客户端报数据库连接池不够等错误,因此例如万人秒杀这种场景,我们绝对不可能通过数据库直接去扣减库存。

关系型数据库不具有可扩展性

可扩展性:

  1. 水平可扩展:越多的服务器会带来更高的负载能力
  2. 对应用透明:服务器的扩展性实现必须与业务的应用逻辑无关,对之透明
  3. 容错性:单个节点的宕机不会导致整个应用的错误
为什么说不具有可扩展性?
  • 方法1:垂直扩展,即升级单台服务器的配置
  • 缺点:
  • 扩展过程复杂,需要人工参与,经常会停机更新
  • 单台服务器性能再高也有瓶颈

因此不符合可扩展性第1条,增加服务器并不会提高负载

  • 方法2:读写分离:“主”服务器实时的把数据分发复制到“从”服务器,“主”服务器只提供写功能,“从”服务器提供只读的功能。
    在读方面它提供了水平的可扩展性,并且对于应用程序来说它也是透明的
    但瓶颈出现在“主”服务器
  • 方法3:分区:即根据一定的规则,把数据切分到不同的数据库上,比如,可以根据用户名的开头字母, 把 A-M 开头的用户存储到一个数据库,把 M-Z 的用户存储到另一个数据库。
    但是这中方式的扩展需要和应用程序的逻辑紧密的结合起来,并且要精心的设计划分的模式和数据库的模式,和系统可能有的查询方式(比方无法进行join操作),它对应用程序的业务逻辑不透明。
NoSql构架演进
  1. KV型NoSql—redis ?
  1. 适用于缓存场景,读远多于写,没有持久化需求
  1. 搜索型NoSql—ElasticSearch ?
  1. 正排索引:文档---->关键词1 + 关键词2 + 关键词…
  2. 倒排索引:关键词 = 文档1 + 文档2 + 文档…
  3. 适用于有条件搜索,尤其是全文搜索的场景
  1. 列式NoSql—HBase
  1. 适用于KV型,且无法预估数据增长的场景
  1. 文档型NoSql—MongoDB

参考自: