《数据密集型系统应用》笔记(一)
(最近得闲,有点想要将之前想看未看挥着看了没有整理的内容进行整理,某种意义上像是还债)
data-intensive applications, 这个概念是相对于计算密集型(Compute-intensive), 到时考虑到目前的AI计算密集型其实也有不少, 但是不是本书讨论的重点;
内容涉及: NoSQL 、消息队列,缓存,搜索索引,批处理和流处理框架
设计的目标: 可靠性,可扩展性和可维护性, (从这点看,有点万变不离其宗的以为, 包括DDD等 架构设计之道,目的都是为了这个,说到底就是架构的本质离不开“人”)
可靠性、可扩展性、可维护性; (Reliability、 scalability, maintainability)
1数据存储 多层, DB cache 、search indexes, streaming, batch process,
从实际的实现层面包括redis mysql, kafka, 还有clickhouse等
可靠性(Reliability)
系统在困境(adversity)(硬件故障、软件故障、人为错误)中仍可正常工作(正确完成功 能,并能达到期望的性能水准)。
具体可以展开讲: 容错(faulttolerant ) faut != failure , fault等于莫非定理中的故障,偏离标准,是无可避免的,而failure则是用户感知到的服务停止,这是可以避免的。
可靠性挑战: 硬件错误大规模部署中不可避免增加故障率; 软件错误,包括各种底层bug等; 人为错误,
可扩展性(Scalability)
有合理的办法应对系统的增长(数据量、流量、复杂性)
(这里指的不是代码的可扩展性), 可扩展性指的是负载的可扩展性 可扩展性要考虑几个维度
- 负载 (客观流量) )
- 性能, 计算效率,比如mapreduce的团团, 平响时间等等, 99th
应对措施:
- 纵向扩展
- 横向扩展 elastic
可维护性(Maintainability)
许多不同的人(工程师、运维)在不同的生命周期,都能高效地在系统上工作(使系统保持 现有行为,并适应新的应用场景)。
(这里也不仅止开发代码的维护,视角要放远 ) 持续的维护阶段,包括修复漏 洞、保持系统正常运行、调查失效、适配新的平台、为新的场景进行修改、偿还技术债、添 加新的功能
这里是对自己的负责和对团队的负责, 也是对后来人的负责
工程师层面:
可操作性(Operability)
便于运维团队保持系统平稳运行。
简单性(Simplicity)
从系统中消除尽可能多的复杂度(complexity),使新工程师也能轻松理解系统。(注意这
和用户接口的简单性不一样。),(这里其实和设计的高内聚低耦合是统一的) 高内聚决定了差异及复杂性在内层, 低耦合决定了依赖的简单性
可演化性(evolability)
使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配。也称为可扩
展性(extensibility),可修改性(modifiability)或可塑性(plasticity)这里就是代码的可扩展性了
运维层面: 人生苦短,关爱运维
在实施层面的注意事项就不提了, 这里注意下规范性和预防层面的
- 通过良好的监控,提供对系统内部状态和运行时行为的可见性(visibility) 可太对了哥, 面板 、SLO、各种监控用起来
- 为自动化提供良好支持,将系统与标准化工具相集成 这就要求入乡随俗或者是尽量使用标准件,而不是定制件,不好维护
- 避免依赖单台机器(在整个系统继续不间断运行的情况下允许机器停机维护) 避免单点
- 提供良好的文档和易于理解的操作模型(“如果做X,会发生Y”) 这个其实难度是很高的
- 提供良好的默认行为,但需要时也允许管理员自由覆盖默认值 这条我倒是觉得是最重要,最有用的, 类似于各种拆箱即用的组件,是他们配置少么? 不是的, 是因为他们的默认行为设置合理 .
- 有条件时进行自我修复,但需要时也允许管理员手动控制系统状态
- 行为可预测,最大限度减少意外
数据模型和查询语言
数据建模, 数据选型
经典的关系数据
当然如果用非关系库,NOSQL的的文档数据表示将更加简单,一个json 即可描述 ,但是描述连接就很麻烦 连接其实也是有意义的,比如推荐, 比如使用 area job school进行协同过滤
NoSql不好描述多对多,这个其实也是设计思想的原罪
关系模型和网络模型(network model)
网络模型 ,“Greater Seattle Area”地区可能是一条记录,每个居住在该地区的用户都可以与之相关联。这允许对多对一和多对多的关系进行建模; 网络模型中记录之间的链接不是外键,而更像编程语言中的指针,访问记录的唯一方法是跟随从根记录起沿这些链路所形成的路径。这被称为访问路径 (access path)。 听着访问效率就很低啊, 而且深度也可能不一
关系模型
行数据= 关系
文档数据库, 在表示多对一和多对多的关系时,关系数据库和文档数据库并没有根本的不同,也就是说文档数据库还是要退化为行数据,使用关联id进行维护;
文档数据!=无模式,而应该叫做 读时模式,schema-on-read , 如果切换过模式呢? 那么感觉读模式的兼容将较为复杂
模式的变更,无论在文档还是关系变更汇总,都是一件大事
在上述情况下,模式的坏处远大于它的帮助,无模式文档可能是一个更加自然的数据模型
查询的数据局部性
文档通常以单个连续字符串形式进行存储,编码为JSON,XML或其二进制变体(如
MongoDB的BSON)。如果应用程序经常需要访问整个文档(例如,将其渲染至网页),那
么存储局部性会带来性能优势
先简单将理解局部性就是将数据进行文档聚合存储
文档+关系数据库
数据查询语言
可以是SQL ,也可以是别的命令式语言,声明式语言
MapReduce查询
MapReduce既不是一个声明式的查询语言,也不是一个完全命令式的查询API,而是处于两 者之间。
e.g
db.observations.mapReduce(function map() {
var year = this.observationTimestamp.getFullYear();
var month = this.observationTimestamp.getMonth() + 1;
emit(year + "-" + month, this.numAnimals);
},
function reduce(key, values) {
return Array.sum(values);
},
{
query: {
family: "Sharks"
},
out: "monthlySharkReport"
});
可以看到 1.search 2. map 3.reduce 4. ou
mapreduce之所以适应大数据 MapReduce是一个相当底层的编程模型,用于计算机集群上的分布式执行
图数据
(有接触的包括neo4j,) 1对多 使用文档型 多对多,那么连接才是数据中最密集的关系,那么使用图更加合适
一个图由两种对象组成:顶点(vertices)(也称为节点(nodes) 或实体(entities)), 和边(edges)( 也称为关系(relationships)或弧 (arcs)
社交关系, 网络图谱 铁路网络
在曾经的一个主数据(cim-service)的项目中有使用到该类型图数据库, sql参考
WITH RECURSIVE
-- in_usa 包含所有的美国境内的位置ID
in_usa(vertex_id) AS (
SELECT vertex_id FROM vertices WHERE properties ->> 'name' = 'United States'
UNION
SELECT edges.tail_vertex FROM edges
JOIN in_usa ON edges.head_vertex = in_usa.vertex_id
WHERE edges.label = 'within'
),
-- in_europe 包含所有的欧洲境内的位置ID
in_europe(vertex_id) AS (
SELECT vertex_id FROM vertices WHERE properties ->> 'name' = 'Europe'
UNION
SELECT edges.tail_vertex FROM edges
JOIN in_europe ON edges.head_vertex = in_europe.vertex_id
WHERE edges.label = 'within' ),
-- born_in_usa 包含了所有类型为Person,且出生在美国的顶点
born_in_usa(vertex_id) AS (
SELECT edges.tail_vertex FROM edges
JOIN in_usa ON edges.head_vertex = in_usa.vertex_id
WHERE edges.label = 'born_in' ),
-- lives_in_europe 包含了所有类型为Person,且居住在欧洲的顶点。
lives_in_europe(vertex_id) AS (
SELECT edges.tail_vertex FROM edges
JOIN in_europe ON edges.head_vertex = in_europe.vertex_id
WHERE edges.label = 'lives_in')
SELECT vertices.properties ->> 'name'
FROM vertices
JOIN born_in_usa ON vertices.vertex_id = born_in_usa.vertex_id
JOIN lives_in_europe ON vertices.vertex_id = lives_in_europe.vertex_id;
cim-service
RDF数据模型、
感觉是个糟粕, 被抛弃的设计