[数据库] 1 SQL and NoSQL

chapter 1
1. 本质,cpu/内存/磁盘,为了持久化,有了文件系统,文件系统对业务逻辑的CRUD支持的并不好,实践中慢慢总结出一套规律,提出标准关系模型,实现SQL,在文件系统层次上抽象出一层支持了CRUD,同时为了解决多应用的并发访问,扩展了较为复杂的一套逻辑,ACID事务/索引等等,大大简1化了业务开发
2. 某种程度上说,这时数据库是中心节点,所有应用通过数据库来实现通信,因此数据库除了存储之外,还要处理并发等问题,书中称之为集成式数据库。
3. 缺点一,内存数据结构和关系型中的table row不一致问题,比如list,nest问题,导致一些开发效率的低下,不过慢慢又有了一层抽象,ORM模型和框架的出现
4. 缺点二,集群效果差,不具备水平扩展性,典型架构就是EMC存储,Oracle数据库,IBM计算,cisco网络,强调竖直扩展性
5. 数据量很大,性能要求很高的场景下,可以考虑NoSQL,其特点主要是水平扩展性强,适用于集群环境,大数据场景,顺应了目前集成式数据库向应用式数据库转换的潮流(每个应用倾向于拥有独立的数据库,取代SQL接口服务可以通过json/xml接口来提供数据服务,成为一种趋势,此时,NoSQL存储只需要关注存储本身即可,关系型数据上层的一些并发acid事务等等逻辑,可以一定程度上转移到应用层去做,底层存储的逻辑就简单一些,带来扩展性)
6. 常见的NoSQL是KV,列式,文档,图数据库
chapter 2
1. 数据模型,不是物理存储,而是CRUD的逻辑存储概念,比如使用SQL要先设计表,索引,通过外键建立关系;要使用KV,则要思考Key如何拼凑,Value的结构选择等等。关系型数据模型利用表和行,可以在一次对多张表中不同的行,做CRUD,提供事务支持
2. NoSQL一般以聚合为单位,支持嵌套,操作的粒度是聚合内部CRUD,文中列举了电子商务系统,用户表,商品表,订单表,地址表,支付表等等,而以文档结构设计,则是用户聚合,订单聚合,订单中嵌套其他信息,减少跨聚合的操作可以带来更好的性能,如何设计schema,取决于访问模式,要考虑最常用的访问模式,根据模式尽量控制访问在同一个聚合中
3. 标准关系型聚合无感知,提供标准的跨表多行事务,好处是灵活的支持多变的数据访问模式,聚合模式的好处则是一旦确定访问模式,可以充分利用聚合内部访问的特点,集群化,水平扩展,将集中的访问模式限制在少量的节点中完成,放宽一部分条件,就可以获得一部分性能
4. KV方案中,主要访问模式利用Key,获得全量Value,也有redis提供基本的操作结构,相对于文档型多变的schema来说,有所区别,文档型支持CRUD聚合中的一部分数据;而列式存储,BigTable/Hbase/Cassandra数据存储按列组织,适用于写少读多场景,且读通常按列读取大量,牺牲写的性能,换取读的性能提升
chapter 3
1. 如何构造聚合取决于最高频的业务场景,复杂的关系SQL会好一些,单多对多的join性能依旧不容乐观,图数据库主要解决此场景,靠牺牲部分写入速度来换取查询的效率,方法是通过维护关系,CRUD都围绕关系展开
2. 存储模型是否需要模式,模式的好处很多方便高效存储和查询(知道的越多,能做的就越多,逻辑也会也复杂);集中式数据库耦合严重,不适合无模式(依赖众多不好处理),应用数据库可以考虑无模式,所谓无模式仅限于聚合内部,当需要更改聚合关系时另当别论
3. 物化视图,实时型适用于写少读多且实时性要求高,定期离线批处理型牺牲实时性来换取线上的性能
chapter 4
1. scale up性价比低且有极限,scale out应运而生,性价比高,同时高并发,高可用,大容量
2. 分片和复制是两个杀手锏,高并发和大容量依赖分片(sharding)逻辑;高可用依赖复制(replication)逻辑,包括主从/对等/同步/异步等等
3. 单点,如果性能可以满足需求则只有高可用问题
4. 分片,伴随着负载均衡,解决性能和容量问题,根据聚合id hash,同时提高读取和写入效率,水平scale out,注意是访问不同数据的场景,访问相同数据的瓶颈分片无法解决
5. 复制,高可用,主从复制,伴随着读写分离,也可以负责均衡,提高读能力,但是写依旧是单点;对等复制,同时提高读写但双写有一致性问题;复制功能伴随着高可用,故障恢复能力,这里有一致性和扩展性的权衡,严格的一致性要求写入半数以上生效或者全部写入才生效,性能会下降的非常严重,而异步复制,会有轻微不一致问题,性能得到大幅度提升,需要根据业务场景来选用一致性级别
chapter 5
1. 单机下的更新一致性,并发更新同一个数据,write-write-conflict,关系型无事务场景下后者会直接覆盖前者的更新,造成lost update,通过读写事务,可以提示后来者更新失败,保证一致性
2. 实现更新一致性的两种方式,悲观方式和乐观方式,加读写锁/CAS条件更新操作,权衡一致性和性能
3. 顺序一致性,单机时上述操作可以满足一致性要求,集群双写时并发导致双写请求顺序不一致,最终结果依旧不一致,顺序一致性需要保证所有节点都按照同样的顺序执行操作;乐观的解决方法,写入后检测到冲突,标记多版本返回到用户侧解决冲突,悲观的方式,使用分布式锁限制并发,权衡因素是延时可用性和一致性,悲观一致性好,延时和吞吐差,极端场景下延时超出超时时间服务不可用,还容易引发死锁问题。
4. 复制中的顺序一致性,主从复制时,一般是单主写,从节点同步主节点的操作顺序保证顺序一致性,对等复制存在多写的可能,需要解决顺序一致性
5. 读取一致性中业务逻辑不一致,read write conflicts。比如业务逻辑中写操作分多个步骤,比如创建订单,更新运费,未最终完成时,读操作并发发生,会造成读取不一致,因为和业务逻辑相关,不论是关系型还是NoSQL都不能完全保证所有业务逻辑的读取一致性,关系型可以保证多表事务,NoSQL可以保证聚合内部原子操作,当然也有分布式事务,依旧是可用性和一致性的权衡,性能差可能导致不可用,一般的做法允许一段时间长度,不一致窗口很短可以满足大部分一致性要求不高的场景
6. 读取一致性中的复制一致性,写未同步所有节点时,读如果读到未更新的节点,因此强一致性要求R+W>N,性能随之下降,因此要区分不同的场景,针对单次请求的一致性要求做不同的复制配置,调整R和W的值
6.1 不同的人通过不同的节点访问相同的数据造成的并发,比如多地域的复制造成的复制不一致
6.2 同一个人通过不同的节点访问相同的数据,此时可以容忍的不一致时间窗口就很长了,只需要保证read-your-own-writes就可以;解决方法一,根据负载均衡策略,可以保证sesison一致性,通过路由到同一个节点来保证一致性不过也降低了负载均衡的能力,读写混合场景,还需要解决写请求的处理,转发到主节点或者切换到主节点完成写,解决方案二,版本戳,请求中携带版本戳,保证可以读到此版本戳下的数据,解决方案三,在客户端做缓存。如果用户通过多个设备接入,则失效,这种场景较少
7. CAP,一致性即前面所述,可用性客户端连接到集群中某个节点,就可以完成读写;分区,集群网络分割后仍可用;
7.1 CA集群,单体满足,若要在集群下满足,牺牲的性能很多,要时时检测集群中是否存在partation,代价高昂,存在则fail整个集群;
7.2 CP集群,可用性放宽松(往往意味着高延时低吞吐),实现强一致性主要是复制的顺序一致性,更新一致性要求要么单写主从,写入时必须保证所有节点全部写入,才能保证读取一致性,一旦某个节点无法沟通确认本次写入,则本次写入失败,集群陷入不可用状态,多写时需要使用协调保证操作一致性
7.3 AP集群,一致性放宽松,来满足可用性(低延时高吞吐),第一步采用主从而不是双写,这样至少主节点的可用性是可以满足的,从节点如果超时依旧不可用;第二步是允许双写,此时会有不一致问题,库存为负数或者预定超额,线下做补偿完成交易,这就提高了可用性
8. 持久性宽松,是否落盘,是否多副本落盘,非持久性写入比如Redis,处理session等等
chapter 6
1. 商业事务和系统事务,商业事务要保证更新一致性,比如最终提交订单式单价汇率等等都变了这种,可以通过版本戳来发现不一致,计数器/时间戳/hash/guid/混合等技术实现版本戳,若想通过版本戳直接判断新旧
2. 数组版本戳,用于检测集群不一致状态,记录各个节点的状态,可以判断出发生了冲突还是读到了旧数据,具体如何处理,依赖实际场景
chapter 7
1. map-reduce hadoop,api =》pig&hive
chapter 8
1. 一致性,一般来说针对单个Key的增删改可以做到原子操作,更新一致性,检测冲突返回客户端解决或者接受新数据,拒绝旧数据
2. 事务,单Key在集群中的要么成功要么失败,通过配置W写入节点数目和复制集节点数目N决定,写入多少节点才返回
3. 案例,会话信息/用户配置信息/购物车数据等简单场景且持久性要求不高,对于关系型/多key事务/复杂操作不适合
chapter 9
1. 一致性,每次写入可以配置复制集多少节点写入算完成,读可以配置是否可以读从节点
2. 事务,单文档内部的原子事务支持
3. 可用性,复制集实现,实现异步主从复制,处理数据冗余,故障切换,读扩展,不停机升级
4. 读扩展,复制集实现,写扩展,分片实现
5. 案例,事件记录/内容管理如博客平台/电子商务/网站分析等较为灵活,无固定模式的场景,对于跨聚合的多种混合操作/查询结构经常变化,即聚合本身划分也要变化场景不适合
chapter 10
1. 列式 Cassandra 行键Key-Value(多个name-Value-timestamp,对应多个列),时间戳充当版本戳,用于判断新旧,双写冲突,淘汰策略等等
2. 一级map,简单列(族),二级map,超级列(族),键空间keyspace对应db,column family对应table
3. 一致性,LSM结构,WAL日志保证单点写入持久化;集群写入,依靠写入配置写入多少节点后返回,创建键空间指定复制集N
4. 事务,行级别原子事务,行内多个列的更新操作,创建新行有事务保证,跨行事务依赖外部设施,比如zk
5. 可用性,极高,无中心设计gossip协议
6. 查询
6.1 依赖设计之初明确查询模式,来设计列族,先创建键空间,然后创建列族(table),colume_family[row key][column name]来插入和访问,GET SET DEL
6.2 支持column name设置索引,使用bitmap实现,多次出现重复键性能较好,
6.3 支持CQL查询,类似SQL
7. 案例。事件记录{appname:{timestamp:.., name:value...}}/计数器/内容管理平台/TTL,对于ACID强需求和查询模式随业务变化场景不适合
chapter 11
1. 关系有方向和属性,节点有属性,一般来说单点,数据量不大,不做分片,可以做复制
2. 一致性,复制带来的主从复制保证
3. 事务,支持复杂事务
4. 可用性,主从复制保证
5. 查询,节点属性查询遍历,可以单独创建节点属性的索引服务,索引到节点主键
6. 扩展性,不支持分片,需要扩展时,大内存单点+主从,更大时,可用domain分片,如根据地域国家等等
7. 案例,互联数据/社交网络/商务领域/运输路线/分派货物/基于位置的服务/推荐引擎,涉及全局图操作过多/不以关系为主的场景不适合
chapter 12
1. 升级兼容性,增加字段,注意过渡节点,线上不同节点不同客户端版本不同的场景,增量迁移
2. 创建新的,留存旧的,增量逐步迁移到新的,删除旧的
chapter 13
架构上,多数据库直接使用/封装每个数据库为rest服务/增强单个数据库满足多种需求
chapter 14
1. 文件系统,分布式文件系统,大文件/流式数据/chunk处理/appendOnlyWrite/SequentialRead场景,如音视频
2. 溯源技术,append only operation log && snapshot技术
chapter 15
1. 如何选择,NoSQL本意提高开发效率,改善访问性能,适用于大数据量和性能较高的场景