# 七周七数据库
读书分享会第一期 2017.02.12
《七周七数据库》 - Eric Redmond
## 预备知识
ACID:原子 一致 隔离 持久
CAP原则:一致性 可用性 分区容错性,在分布式环境下,至多只能同时满足其二
“小明,你的数据库作业呢?”“我可以今天提交一半的作业,或者明天提交全部的作业,但无法在今天提交全部的作业。”“...小明你给我滚出去!”
小知识点:
* 原子性:原子性代表中间状态的透明性,想象从a账户向b账户转500块,则{ a: 1000, b: 1000 }和{ a: 500, b: 1500 }的读取都是正确的,而不应该读取到{ a: 500, b: 1000 }或{ a: 1000, b: 1500 }的状态
* 一致性:根据CAP原则,分布式环境下有时只提供最终一致性
* 数据库用四个隔离级别,对应对幻读、不可重复读、脏读有着不同程度的避免。
* 数据库通过transaction(事务)来保障原子性,通常的办法是通过先写log来实现
* 锁:分为读锁和写锁等,各种数据库和引擎提供的最小锁粒度也会不同
* MVCC:多版本控制,通过填写额外的更新时间、删除实现等来保证数据的正确性
* 其他知识点,如b+书、lsm树、hash table和hash tier等等
## N*Sql历史
No Sql年代:层次化数据库
Know Sql年代:RDBMS
No Sql年代:CAP原则催生了一系列做出不同取舍和提供不同功能的NoSql数据库
New Sql年代:无论是ACID还是数据关系都是数据的本质,No Sql数据库的定位从替换RDBMS转向辅佐RDBMD,同时也诞生了为大数据而生的time series db(比如Riak TS)和具有reactive(响应式)特性的(比如Rethink DB)等新型数据库。
## 7数据库
RDBMS:Postgres
KV:Riak KV,Redis
列型数据库:HBase
文档型数据库:Mongo,Couch
图形数据库:Neo4j
小知识点:
* 基于列和基于行的区别:想象我们有数据{ id: 1, a: 1, b: 1 }和{ id: 2, a: 2, b: 1 },对于列数据库我们存储的数据相当于[{ id: 1, data: { a: 1, b: 1 } }, { id: 2, data: { a: 2, b: 2 }}],而基于行的存储则是:{ columns: [id, a, b ],data: [1, 1, 1], [2, 2, ] }。列型数据库(或schemaless)的设计理念提高了灵活性,但也因此牺牲了性能(想想为什么)
## Postgres
### 第一天:关系,CRUD和链接
### 第二天:高级查询,事务、存储过程、视图、触发器、规则、数据透视表
高级查询包括聚合查询、分组和窗口(PARTITION BY)等
规则是对如何修改解析过的查询树(AST,抽象语法树)的描述
### 第三天:全文检索和多维查询
### 补充:
PSql vs. MySql:PSql有良好的代码结构方便学习源码和插件开发,因此社区有大量插件,如GIS、全文搜索、多维空间距离等等;有丰富的存储过程;支持tuple级别的streaming replication等等。
## Riak KV
### 第一天:CRUD,链接和MIME
Riak KV通过桶名+Key来定位一个数据
Riak KV可以在数据之间建立链接
Riak KV支持不同MIME Type的数据,可以用来自建CDN等
### 第二天:MapReduce和服务器集群
Riak KV支持在请求中包含mapreduce传入的方法;或者存储在服务器端,请求时直接调用
Riak KV的集群:Riak环,是基于一致性hash的
### 第三天:解决冲突和扩展Riak KV
Riak KV通过向量时钟和保存多版本的方式来处理冲突
Riak KV提供了pre / post commit hook
### 补充:
CAP:Riak KV基于“CAP可以在每个桶或者每个请求的基础上改变”这一观点
## HBase
HBase出于Hadoop
### 第一天:CRUD和表管理
HBase为大数据而生,提供了单机模式、单节点伪分布式模式、分布式模式
HBase提供了列组的概念
### 第二天:处理大数据
bloom过滤器:是一种通过位翻转实现的二分过滤器,其存储空间(无限)小于哈希方式,但存在伪阳性的概率。HBase支持使用bloom过滤器确定某行是否存在某个列。
HBase的使用区域在不同节点上存储不同的数据段(横切)。
### 第三天:放入云端
Thrift
Whirr:实现了虚拟集群的管理,支持EC2和RackSpace服务器等,支持Hadoop、HBase、Cassandra、ZooKeeper等集群。
### 补充:
HBase在CAP上是CP。
大数据方面google很早就放弃hadoop力挺spark了,以及现在有很多项目已经开始用ts db作为架构的数据存储工具了。
## Mongo
Mongo出自humongous(巨大)而非mango。
### 第一天:CRUD和嵌套
Mongo存储的格式是BSON
### 第二天:索引、分组、mapreduce
### 第三天:副本集、分片、GIS和GridFS
sharding分片是mongo的横切方案,每个sharding再建立m-s的结构。
### 补充:
Mongo已经支持left join了哦。这也印证了之前所说的New Sql出现的时代背景。以及最近出了好几件安全方面的事件...
## CouchDB
### 第一天:CRUD、Futon
Futon是Couch提供的web管理界面。
### 第二天:视图
### 第三天:进阶视图、Changes API和复制数据
CouchDB提供了Changes API来帮助应用监控数据的变化并立即更新(reactive)
BigCouch基于CouchDB并实现了分片与复制策略。
## Neo4j
Neo4j是“白板友好”的数据库
### 第一天:图、Groovy和CRUD
Neo4j数据分为点和边,并通过加tag(s)来加以区分不同的点和边。
Neo4j有java/scala写成,其查询方式包括server mode的restful(极度不推荐)、cypher(cypher是一个graph db查询语言的标准),以及embeded mode的java和gremlin(使用groovy)。
### 第二天:rest、索引与算法
### 第三天:分布式高可用性
可以用ZK管理neo4j集群
### 补充:
我本人很喜欢graph db,以及neo4j,是一个ACID的事务数据库,且相对灵活,但是图数据库仍存在一个问题:既定的抽象可能在后期业务需求改变时造成一定的影响,而graph db本身的核心在于在内存中保存链接关系,因此也出现了许多存储层使用非图形存储引擎(比如psql)的实现,或者使用多次查询而非join的方式一定程度上解决n°关系查询时间非线性的问题。
## Redis
### 第一天:CURD与数据类型
数据类型包括哈希、列表、集合、有序集合、范围等
可以设置expire time,特别适合做缓存
### 第二天:高级用法,分布
Redis还支持发布-订阅,因此也被用来做task-queue/message-queue等。
Redis持久化的模式包括快照与AOF(append only file)。
### 第三天:与其他数据库合作
### 补充:
Redis的理念其实就是New Sql了。一句话,就是赞。
## 补充:Time Series DB
TS DB是一种immutable的数据库,即历史数据一旦写入无法修改,比如2017.02.12这天笨笨的颜值是一个定值,无论是在一天之后还是一周之后或是10年之后来看,2017.02.12这天的笨笨都是这般帅得掉渣,这就是immutable的概念。基于这一点,数据库在存储实现时就可以连续的读写磁盘,大大提高了性能。
同样有immutable概念的还有Block Chain区块链,两者的区别是可以将Block Chain想象成有成千上万master节点的集群,这样的实现在提供了去中心化的同时却导致审核transaction的速度大大降低,于是出现了许多offline transaction的手段。关于PoW与PoS、默克尔-帕特里夏树、EVM(ethereum virtual machine)等等概念,感兴趣的话可以了解一下哦。
## 最后的最后
“老板我花费多时搭建了一个高可用的数据库集群了!”“好样的,小明。现在我们的产品有多少用户了?”“算上我和你的话,两个。”“...小明,你特么给我滚出去!”