分布式系统基本概念
分布式系统类型
-
Client / Server
- 客户端发送请求,服务器完成操作,发回响应
-
P2P (Peer‐to‐peer)
- 分布式系统中每个节点都执行相似的功能
- 整个系统功能完全是分布式完成的
- 没有中心控制节点
-
Master / workers
- 有一个/一组节点为主,进行中心控制协调
- 其它多个节点为workers,完成具体工作
故障类型
-
Fail stop
- 当出现故障时,进程停止/崩溃
-
Fail slow
- 当出现故障时,运行速度变得很慢
-
Byzantine failure
- 包含恶意攻击
CAP
一致性、可用性、分区容错性三者不可兼容
分布式文件系统
-
本地文件系统 (Local File System)
- Linux ext4, Windows ntfs, Mac OS hfs
-
NFS:Sun’s Network File System,client/server架构
-
Stateless:server无状态,故障重启即可
-
Idempotent:操作幂等性,Client无响应,重试即可
-
Client cache:缓存读写的数据,避免远程操作
-
一致性问题:写回,写操作关闭时,将写同步到server
-
其他已缓存的怎么知道缓存是否过期?每次使用缓存,发送GETATTR请求,验证缓存是否过期
- 但是效率很低
-
-
-
AFS (Andrew File System)
-
解决cache过期问题:Client 获得一个文件时,在server上登记,当server发现文件修改时,向已登记的client发一个callback,Client收到callback删除缓存的文件
-
其他区别:
- AFS缓存整个文件,NFS数据页为单位
- AFS缓存在本地硬盘中,NFS的缓存是在内存中的
- AFS open: 将把整个文件从Server读到Client
- 有统一的名字空间,而NFS可以mount到任何地方
-
Google File System和HDFS
-
GFS/HDFS:Google File System 、Hadoop Distributed File System
- Client/server架构
- 主要功能:大块数据顺序读写、并行追加
- 不支持:修改文件
-
文件切分成定长的数据块(默认为64MB大小的数据块)
-
每个数据块独立地分布存储在Data Node上
-
默认每个数据块存储3份,在3个不同的data node上
-
open:与Name Node通信一次
-
read:直接与Data Node通信,从多个副本中选择最佳的Data Node读取数据,支持多副本并行读取
-
write:3个副本:本机、本机柜、其它机柜
- 数据发送到Datanode,形成pipeline传递副本数据
- 不支持并发写
- 支持并行的append
Key‐Value Store
-
Dynamo: 由Amazon公司研发
-
p2p架构:多个nodes互连形成环形分布式系统
-
token= hash(key),每个node设置存储的token区间,实现横向扩展
-
故障迁移:类似一致性哈希,移交到下一个顺序的节点
-
数据备份:顺位备份两个副本
-
读写强一致性:Quorum (N, W, R)
- 满足R+W>N,容错W-1
-
不支持事务
-
-
Bigtable / HBase: Bigtable起源于Google公司, Hbase是开源实现
-
Master/server架构,底层使用HDFS存储ssTable
-
表的组成:Row key、Column Family、Column Key
-
存储:按row key顺序,列式存储
-
Hbase操作:
-
create 'mytable', 'mycf’ put 'mytable', 'abc', 'mycf:a', '123' scan 'mytable'
-
-
索引结构:LSM-Tree
-
由多层组成,大小指数级增长
-
每层都是一个有序索引,例如B+树
-
都是对磁盘的顺序写,利用bloom filter 快速判断当前层有没有数据
-
-
-
Cassandra:由Facebook研发,后成为Apache开源项目
- RocksDB: 由Facebook研发,是在Google LevelDB基础上形成的
Distributed Coordination: ZooKeeper
-
分布式问题:选主、节点状态、一致性共识
-
ZooKeeper:维护一组共同的数据状态
-
数据模型:Data Tree
- Name: 一个Znode可以用一条从根开始的路径唯一确定,如/c/f
- Data: 可以存储任意数据,但长度不超过1MB
- Version:版本号
- Regular/Ephemeral:正常的/临时的
-
API:
- 创建Znode/删除Znode/判断Znode存在
- 读Znode数据/修改Znode数据
- 找孩子Znode
-
Watch机制
- exists(path, watch),当Znode被删除/新建时,收到通知
-
Linearizable writes:写可串行化,因为Leader复制数据到Follower
-
FIFO client order,不同Client之间的读写顺序没有任何保证
-
-
ZAB
-
两个主要工作模式
-
Broadcast: Leader向Follower广播新的写操作
-
2PC:
- Propose阶段:Leader把一个新的txn写入本地log, 广播Propose这个txn,每个Follower收到Propose后,写入本地log,向Leader发回Ack
- Commit阶段: Leader收到 f个Ack后,写Commit到log, 广播Commit,然后修改自己的ZooKeeper树。 Follower收到Commit消息,写Commit到log,然后修改ZooKeeper树
-
-
Recovery:竞争新的Leader,新的Leader进行恢复
- 每个节点选择Leader为看到max(TxnID)为最大的节点
-
-
-
应用:
-
配置信息
- 把配置信息存储在一个确定路径的Znode中
- 利用Watch机制获得配置信息的变化
-
成员管理
- 用一个Znode代表节点组,每个成员都在group下面创建一个ephemeral 的孩子
- 当某个成员崩溃了,那么它对应的孩子就被删除
-
分布式锁
- 可以把lock对应为一个Znode
- 加锁=创建Znode,解锁=删除Znode
- 加锁不成功,可以用watch,当Znode被删除时,可以得到通知
-
Document Store
树状结构数据模型
-
JSON
- 数据类型:string, number, true/false, null、Object{k:v}、Array[]
-
Google Protocol Buffers: Google推出,最初用于实现网络协议
- 数据格式要提前声明,树形的
MongoDB
JSON是基本数据类型,存储为BSON二进制表示
组成:
- Database:关系型中的数据库概念
- Collection:关系型中的table概念
- Document:关系型中的记录概念
API and Query Model
-- 创建表 和 插入数据
db.student.insert({
student_id : 131234,
name : “张飞”,
major : “计算机”,
year: 2013
})
-- 查询数据
db.student.find(
{ major : “计算机” },
{name : 1, year:1, _id:0}
)
-- where + group by
db.student.aggregate( [
{$match : { major : “计算机” }},
{$group : { _id:{year: “$year”},
cnt: {$sum: 1}}
])
架构:
-
单机
-
Sharding 垂直分片
-
Write Concern:什么时候认为写完成
- Unacknowledged: 写请求发送了,就认为完成
- Acknowledged:MongoDB应答了收到写请求,就认为完成
- Journaled:MongoDB把写请求记录在硬盘上的日志中,认为完成
图存储系统(Graph Database)
图数据模型
-
G=(V, E)
- V:顶点(Vertex)的集合
- E:边(Edge)的集合
-
图数据存储系统:存储图顶点和边,提供顶点和边的查询,类似OLTP
-
图运算系统:以图为基础运行大规模算法,类似OLAP
Neo4j
-
文件存储:
- 顶点、边、属性:分别存储所有node, relationship, property的文件,unique id标识
- Relationship:同一个node的relationship形成一个双向链表
- Property:同一个node/relationship的property形成一个单向链表
-
Node/Rel cache:对node, relationship, property缓冲
-
Traversal:遍历操作
-
Cypher:图数据库查询语言
-- node
(nodename:type, {property_key:value, key:value})
(张飞)
(张飞:Student)
(张飞:Student,{name:“张飞”,major : “计算机”, year: 2013})
(体系结构:Course,{name:“体系结构”})
-- Relationship
‐ [name:type, {property_key:value, key:value}] ‐ >
‐[:Takecourse]‐ >
‐[:Takecourse,{year:2014, grade:85}]‐ >
-- Create
CREATE (张飞:Student,{name:“张飞”, major : “计算机”, year: 2013})
CREATE (体系结构:Course,{name:“体系结构”})
CREATE (张飞) ‐[:Takecourse,{year:2014, grade:85}]‐>(体系结构)
-- Match
-- 找具有name:”张飞”属性的顶点
MATCH (x {name:”张飞”}) RETURN x
-- 找到所有选修体系结构课程的学生顶点
MATCH (x:Student)‐[:Takecourse]‐>(:Course {name:”体系结构”}) RETURN x
-- 找到既选修体系结构又选修数据库的顶点
MATCH ({name:”数据库”})<‐[:Takecourse]‐(x)‐[:Takecourse]‐>({name:”体系结构”}) RETURN x
-- 找到所有选修体系结构课程的学生顶点,要求学生是2013年入学的
MATCH (x:Student)‐[:Takecourse]‐>(:Course {name:”体系结构”})
WHERE x.year=2013
RETURN x
-- 找到所有选修体系结构课程的学生顶点, 要求学生没有选修过操作系统
MATCH (x:Student)‐[:Takecourse]‐>(:Course {name:”体系结构”})
WHERE NOT (x)‐[:Takecourse]‐>(:Course {name:”操作系统”})
RETURN x
-- 有路径从a 到 b
(a)‐[*]‐>(b)
-- 有路径从a 到 b,路径最短3步,最长5 步
(a)‐[*3..5]‐>(b)
-
HA: 多副本机制
- 主副本把transaction log发送到从副本
- 从副本replay log从而执行同样的操作
JanusGraph:一个分布式图数据库
- Gremlin查询语言
RDF和Sparql
-
RDF(Resource Description Framework)
- 每个RDF记录是三元组(subject 主, predicate 谓, object 宾)
-
SPARQL(读作sparkle):RDF的查询语言
多模数据库系统(Multi‐Model DB)