-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
216 lines (216 loc) · 157 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[越来越火的图数据库究竟是什么]]></title>
<url>%2F%E8%B6%8A%E6%9D%A5%E8%B6%8A%E7%81%AB%E7%9A%84%E5%9B%BE%E6%95%B0%E6%8D%AE%E5%BA%93%E7%A9%B6%E7%AB%9F%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F%2F</url>
<content type="text"><![CDATA[随着社交、电商、金融、零售、物联网等行业的快速发展,现实社会织起了了一张庞大而复杂的关系网,传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随数据量呈几何级数增长,亟需一种支持海量复杂数据关系运算的数据库,图数据库应运而生。 世界上很多著名的公司都在使用图数据库。比如: 社交领域:Facebook, Twitter,Linkedin用它来管理社交关系,实现好友推荐 零售领域:eBay,沃尔玛使用它实现商品实时推荐,给买家更好的购物体验 金融领域:摩根大通,花旗和瑞银等银行在用图数据库做风控处理 汽车制造领域:沃尔沃,戴姆勒和丰田等顶级汽车制造商依靠图数据库推动创新制造解决方案 电信领域:Verizon, Orange和AT&T 等电信公司依靠图数据库来管理网络,控制访问并支持客户360 酒店领域:万豪和雅高酒店等顶级酒店公司依使用图数据库来管理复杂且快速变化的库存 既然图数据库应用这么广泛,越来越多的企业和开发者开始使用它,那它究竟什么过人之处呢,下面我们来揭开它的神秘面纱。 1. Why Graph DB?学过数据结构这么课程的同学脑海中应该或多或少有图的概念。 1.1 什么是图?图由两个元素组成:节点和关系。 每个节点代表一个实体(人,地,事物,类别或其他数据),每个关系代表两个节点的关联方式。这种通用结构可以对各种场景进行建模 - 从道路系统到设备网络,到人口的病史或由关系定义的任何其他事物。 1.2 什么是图数据库?图数据库(Graph database)并非指存储图片的数据库,而是以图这种数据结构存储和查询数据。 图形数据库是一种在线数据库管理系统,具有处理图形数据模型的创建,读取,更新和删除(CRUD)操作。 与其他数据库不同,关系在图数据库中占首要地位。这意味着应用程序不必使用外键或带外处理(如MapReduce)来推断数据连接。 与关系数据库或其他NoSQL数据库相比,图数据库的数据模型也更加简单,更具表现力。 图形数据库是为与事务(OLTP)系统一起使用而构建的,并且在设计时考虑了事务完整性和操作可用性。 1.3 两个重要属性根据存储和处理模型不同,市面上图数据库也有一些区分。 比如:Neo4J就是属于原生图数据库,它使用的后端存储是专门为Neo4J这种图数据库定制和优化的,理论上说能更有利于发挥图数据库的性能。 而JanusGraph不是原生图数据库,而将数据存储在其他系统上,比如Hbase。 ① 图存储一些图数据库使用原生图存储,这类存储是经过优化的,并且是专门为了存储和管理图而设计的。并不是所有图数据库都是使用原生图存储,也有一些图数据库将图数据序列化,然后保存到关系型数据库或者面向对象数据库,或其他通用数据存储中。 ② 图处理引擎原生图处理(也称为无索引邻接)是处理图数据的最有效方法,因为连接的节点在数据库中物理地指向彼此。非本机图处理使用其他方法来处理CRUD操作。 2. 对比2.1 与NoSQL数据库对比NoSQL数据库大致可以分为四类: 键值(key/value)数据库 列存储数据库 文档型数据库 图数据库 分类 数据模型 优势 劣势 举例 键值数据库 哈希表 查找速度快 数据无结构化,通常只被当作字符串或者二进制数据 Redis 列存储数据库 列式数据存储 查找速度快;支持分布横向扩展;数据压缩率高 功能相对受限 HBase 文档型数据库 键值对扩展 数据结构要求不严格;表结构可变;不需要预先定义表结构 查询性能不高,缺乏统一的查询语法 MongoDB 图数据库 节点和关系组成的图 利用图结构相关算法(最短路径、节点度关系查找等) 可能需要对整个图做计算,不利于图数据分布存储 Neo4j、JanusGraph 2.2 与关系型数据库对比关系型数据库实际上是不擅长处理关系的。很多场景下,你的业务需求完全超出了当前的数据库架构。 举个栗子:假设某关系型数据库中有这么几张用户、订单、商品表: 当我们要查询:“用户购买了那些商品?” 或者 “该商品有哪些客户购买过?” 需要开发人员JOIN几张表,效率非常低下。 而“购买该产品的客户还购买了哪些商品?”类似的查询几乎不可能实现。 关系查询性能对比在数据关系中心,图形数据库在查询速度方面非常高效,即使对于深度和复杂的查询也是如此。在《Neo4j in Action》这本书中,作者在关系型数据库和图数据库(Neo4j)之间进行了实验。 他们的实验试图在一个社交网络里找到最大深度为5的朋友的朋友。他们的数据集包括100万人,每人约有50个朋友。实验结果如下: 深度 MySQL执行时间(s) Neo4J执行时间(s) 返回记录数 2 0.016 0.01 ~2500 3 30.267 0.168 ~110 000 4 1543.505 1.359 ~600 000 5 未完成 2.132 ~800 000 在深度为2时(即朋友的朋友),两种数据库性能相差不是很明显;深度为3时(即朋友的朋友的朋友),很明显,关系型数据库的响应时间30s,已经变得不可接受了;深度到4时,关系数据库需要近半个小时才能返回结果,使其无法应用于在线系统;深度到5时,关系型数据库已经无法完成查询。而对于图数据库Neo4J,深度从3到5,其响应时间均在3秒以内。 可以看出,对于图数据库来说,数据量越大,越复杂的关联查询,约有利于体现其优势。从深度为4/5的查询结果我们可以看出,图数据库返回了整个社交网络一半以上的人数。 3. Neo4J 和 JanuasGraph根据DB-Engines最新发布的图数据库排名,Neo4J仍然大幅领先排在第一位: Neo4J Neo4J是由Java实现的开源图数据库。自2003年开始开发,直到2007年正式发布第一版,并托管于GitHub上。 Neo4J支持ACID,集群、备份和故障转移。目前Neo4J最新版本为3.5,分为社区版和企业版,社区版只支持单机部署,功能受限。企业版支持主从复制和读写分离,包含可视化管理工具。 JanusGraph JanusGraph是一个Linux基金会下的开源分布式图数据库 。JanusGraph提供Apache2.0软件许可证。该项目由IBM、Google、Hortonworks支持。JanusGraph是由TitanDB 图数据库修改而来,TitanDB从2012年开始开发。目前最新版本为0.3.1。 JanusGraph支持多种储存后端(包括Apache Cassandra、Apache HBase、Bigtable、Berkeley DB)。JanusGraph的可扩展性取决于与JanusGraph一起使用的基础技术。例如,通过使用Apache Cassandra作为存储后端,可以将JanusGraph简单地扩展到多个数据中心。 JanusGraph通过与大数据平台(Apache Spark,Apache Giraph,Apache Hadoop)集成,支持全局图数据的分析、报告和ETL。 JanusGraph通过外部索引存储(Elasticsearch,Solr,Lucene)支持地理、数字范围和全文搜索。 3.1 标记属性图模型 (1)节点 节点是主要的数据元素 节点通过关系连接到其他节点 节点可以具有一个或多个属性(即,存储为键/值对的属性) 节点有一个或多个标签,用于描述其在图表中的作用 示例:人员节点与Car节点 (2)关系 关系连接两个节点 关系是方向性的 节点可以有多个甚至递归的关系 关系可以有一个或多个属性(即存储为键/值对的属性) (3)属性 属性是命名值,其中名称(或键)是字符串 属性可以被索引和约束 可以从多个属性创建复合索引 (4)标签 标签用于将节点分组 一个节点可以具有多个标签 对标签进行索引以加速在图中查找节点 本机标签索引针对速度进行了优化 4. Cypher图查询语言Cypher是Neo4j的图形查询语言,允许用户存储和检索图形数据库中的数据。 举例,我们要查找Joe的所以二度好友: 查询语句如下:12345678MATCH (person:Person)-[:KNOWS]-(friend:Person)-[:KNOWS]- (foaf:Person)WHERE person.name = "Joe" AND NOT (person)-[:KNOWS]-(foaf)RETURN foaf Joe认识Sally,Sally认识Anna。 Bob被排除在结果之外,因为除了通过Sally成为二级朋友之外,他还是一级朋友。 5. 小结图数据库应对的是当今一个宏观的商业世界的大趋势:凭借高度关联、复杂的动态数据,获得洞察力和竞争优势。国内越来越多的公司开始进入图数据库领域,研发自己的图数据库系统。对于任何达到一定规模或价值的数据,图数据库都是呈现和查询这些关系数据的最好方式。而理解和分析这些图的能力将成为企业未来最核心的竞争力。]]></content>
<categories>
<category>BigData</category>
<category>图数据库</category>
</categories>
<tags>
<tag>图数据库</tag>
<tag>Neo4J</tag>
<tag>JanusGraph</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Atlas开发指南(中文版)]]></title>
<url>%2FAtlas%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97(%E4%B8%AD%E6%96%87%E7%89%88)%2F</url>
<content type="text"><![CDATA[笔者近期在和团队的小伙伴进行数据资产管理方向的探索,本书的翻译基于 Apache Atlas v1.1 版本。希望对大家有帮助,阅读过程中遇到问题欢迎留言或与我联系。 点击我打开《Atlas开发指南(中文版)》 手机端浏览,在Gitbook阅读界面下滑即可看到左上角类似“三”的目录图标,点击即可展开目录进行切换。 阅读过程中如果有问题,请下方评论中反馈给我~]]></content>
<categories>
<category>BigData</category>
<category>Atlas</category>
</categories>
<tags>
<tag>Atlas</tag>
<tag>Gitbook</tag>
<tag>元数据管理</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用Atlas进行元数据管理之容错与高可用]]></title>
<url>%2F%E4%BD%BF%E7%94%A8Atlas%E8%BF%9B%E8%A1%8C%E5%85%83%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86%E4%B9%8B%E5%AE%B9%E9%94%99%E4%B8%8E%E9%AB%98%E5%8F%AF%E7%94%A8%2F</url>
<content type="text"><![CDATA[1. 介绍Apache Atlas使用各种系统并与之交互,为数据管理员提供元数据管理和数据血缘信息。通过适当地选择和配置这些依赖关系,可以使用Atlas实现服务的高可用性。本文档介绍了Atlas中的高可用性支持状态,包括其功能和当前限制,以及实现此高级别可用性所需的配置。 在Atlas文档高级架构章节(请参阅我翻译的《Atlas开发指南(中文版)》)概述了构成Atlas的各种组件。下面提到的各种组件的选项,都是基于上述文档中的架构描述,在继续阅读本文之前推荐先行阅读文档中相关章节。 2. Atlas Web Service目前,Atlas Web Service有一个限制,即它一次只能有一个活动实例。在早期版本的Atlas中,可以配置备份实例并使其可用。但是,需要手动故障转移才能使此备份实例处于活动状态。 从此版本开始,Atlas将通过自动故障转移支持活动(active)/被动(passive)配置中的多个Atlas Web服务实例。这意味着用户可以同时在不同的物理主机上部署和启动Atlas Web Service的多个实例。其中一个实例将自动选为“active”实例以服务用户请求。其他实例将自动被视为“passive”。如果“active”实例因故意停止或由于意外故障而变得不可用,则其他实例之一将自动被选为“active”实例并开始为用户请求提供服务。 “active”实例是唯一可以正确响应用户请求的实例。它可以创建,删除,修改或响应元数据对象上的查询。 “passive”实例将接受用户请求,但会使用HTTP重定向将其重定向到当前已知的“active”实例。具体而言,passive实例本身不会响应对元数据对象的任何查询。但是,所有实例(active和passive)都将响应返回有关该实例的信息的管理请求。 在高可用性模式下配置时,用户可以获得以下操作收益: 维护间隔期间不间断的服务:如果需要关闭Atlas Web Service的活动实例以进行维护,则另一个实例将自动变为活动状态并可以为请求提供服务。 意外故障时的不间断服务:如果Atlas Web Service的活动实例因软件或硬件错误而失败,则另一个实例将自动变为活动状态并可以为请求提供服务。 在以下小节中,我们将介绍为Atlas Web Service设置高可用性所需的步骤。我们还描述了如何设计部署和客户端以利用此功能。最后,我们描述了底层实现的一些细节。 2.1 在Atlas中设置高可用性功能设置高可用性功能必须满足以下先决条件。 确保在一组计算机上安装Apache Zookeeper(建议至少使用3台服务器进行生产)。 选择2个或更多物理计算机以运行Atlas Web Service实例。这些机器定义了我们称之为Atlas的“服务器集合”。 要在Atlas中设置高可用性,必须在atlas-application.properties文件中定义一些配置选项。虽然在配置页面中定义了完整的配置项列表,但本节列出了一些主要选项。 高可用性是Atlas中的可选功能。因此,必须通过将配置选项atlas.server.ha.enabled设置为true来启用它。 接下来,定义标识符列表,每个物理机一个用于Atlas Web Service实例。这些标识符可以是简单的字符串,如id1,id2等。它们应该是唯一的,不应包含逗号。 将这些标识符的逗号分隔列表定义为选项atlas.server.ids的值。 对于每台物理计算机,将IP地址/主机名和端口列为配置atlas.server.address.id的值,其中id表示此物理计算机的标识符字符串。 例如,如果您选择了2台主机名为host1.company.com和host2.company.com的计算机,则可以按如下方式定义配置选项:123atlas.server.ids=id1,id2atlas.server.address.id1=host1.company.com:21000atlas.server.address.id2=host2.company.com:21000 定义将由Atlas高可用性功能使用的Zookeeper集群。 1atlas.server.ha.zookeeper.connect=zk1.company.com:2181,zk2.company.com:2181,zk3.company.com:2181 您可以查看为高可用性功能定义的其他配置选项,并根据需要在atlas-application.properties文件中进行设置。 对于生产环境,还必须在高可用性模式下设置Atlas所依赖的组件。这将在以下部分中详细介绍。按照这些说明设置和配置它们。 在所选物理计算机上安装Atlas软件。 将使用上述步骤创建的atlas-application.properties文件复制到所有计算机的配置目录中。 启动从属组件。 启动Atlas Web Service的每个实例。 要验证高可用性是否正常,请在安装了Atlas Web Service的每个实例上运行以下脚本。1$ATLAS_HOME/bin/atlas_admin.py -status 此脚本可以打印以下值之一作为响应: ACTIVE:此实例处于活动状态,可以响应用户请求。 PASSIVE:这个实例是被动的。它会将收到的任何用户请求重定向到当前活动实例。 BECOMING_ACTIVE:如果服务器正在转换为ACTIVE实例,则会打印出来。服务器无法在此状态下为任何元数据用户请求提供服务。 BECOMING_PASSIVE:如果服务器正在转换为PASSIVE实例,则会打印出来。服务器无法在此状态下为任何元数据用户请求提供服务。 在正常操作情况下,这些实例中只有一个应该打印值ACTIVE作为对脚本的响应,而其他实例将打印PASSIVE。 2.2 配置客户端以使用高可用性功能可以通过两种方式访问Atlas Web Service: 使用Atlas Web UI:这是一个基于浏览器的客户端,可用于查询存储在Atlas中的元数据。 使用Atlas REST API:由于Atlas公开了RESTful API,因此可以使用任何标准REST客户端,包括其他应用程序中的库。实际上,Atlas附带了一个名为AtlasClient的客户端,可以作为构建REST客户端访问的示例。 为了利用客户端中的高可用性功能,有两种选择。 (1)使用中间代理实现对Atlas的高可用性访问的最简单的解决方案是安装和配置一些中间代理,该代理具有基于状态透明地切换服务的能力。一个这样的代理解决方案是HAProxy。 以下是可以使用的示例HAProxy配置。请注意,此提供仅用于说明,而不是推荐的生产配置。请参阅HAProxy文档以获取适当的说明。1234567891011121314frontend atlas_fe bind *:41000 default_backend atlas_bebackend atlas_be mode http option httpchk get /api/atlas/admin/status http-check expect string ACTIVE balance roundrobin server host1_21000 host1:21000 check server host2_21000 host2:21000 check backuplisten atlas bind localhost:42000 上面的配置绑定HAProxy以监听端口41000以获取传入的客户端连接。然后,它会根据HTTP状态检查将连接路由到主机host1或host2。状态检查是使用REST URL /api/atlas/admin/status上的HTTP GET完成的,仅当HTTP响应包含字符串ACTIVE时才被视为成功。 (2)使用活动实例自动检测如果不想设置和管理单独的代理,则使用高可用性功能的另一个选项,是构建能够检测状态和重试操作的客户端应用程序。在这样的设置中,可以使用形成整体的所有Atlas Web Service实例的URL启动客户端应用程序。然后,客户端应在每个上面调用REST URL/api/atlas/admin/status以确定哪个是活动实例。 Active实例的响应形式为{Status:ACTIVE}。此外,当客户端在操作过程中面临任何异常时,它应该再次确定哪些剩余URL处于活动状态并重试该操作。 Atlas附带的AtlasClient类可用作示例客户端库,该库实现处理集合并选择正确的Active Server实例的逻辑。 Atlas中的实用程序(如quick_start.py和import-hive.sh)可以配置为与多个服务器URL一起运行。在此模式下启动时,AtlasClient会自动选择并使用当前活动实例。如果在两者之间设置了代理,则在运行quick_start.py或import-hive.sh时可以使用其地址。 2.3 Atlas高可用性的实现细节Atlas高可用性工作在主JIRA ATLAS-510下进行跟踪。在其下提交的JIRA提供了有关如何实施高可用性功能的详细信息。在高层次上,可以调出以下几点: 自动选择Active实例,以及通过领导者选举算法自动故障转移到新的Active实例。 对于领导者选举,我们使用Leader Latch Recipe of Apache Curator。 Active实例是唯一一个在后端存储中初始化,修改或读取状态以保持一致的实例。 此外,当实例被选为活动时,它会刷新来自后端存储的任何缓存信息以获取最新信息。 servlet过滤器确保只有活动实例服务用户请求。如果被动实例接收到这些请求,它会自动将它们重定向到当前活动实例。 3. 元数据存储Atlas使用JanusGraph存储和管理元数据。默认情况下,Atlas使用独立的HBase实例作为JanusGraph的底层存储。为了为元数据存储提供HA,我们建议将Atlas配置为使用分布式HBase作为JanusGraph的底层存储。要将Atlas配置为在HA模式下使用HBase,请执行以下操作: 选择在HA模式下设置的现有HBase群集,以在Atlas(OR)中进行配置在HA模式下设置新的HBase群集。 如果为Atlas设置HBase,请按照Atlas官网“Installation Steps”,列出的HBase的相关设置说明进行操作。 建议在使用Zookeeper进行协调的不同物理主机上的群集中使用多个HBase主服务器(至少2个),以提供HBase的冗余和高可用性。 有关在atlas.properties中配置以使用HBase设置Atlas的选项,请参阅我翻译的《Atlas开发指南(中文版)》中“配置”章节。 4. 索引存储如上所述,Atlas通过JanusGraph索引元数据以支持全文搜索查询。为了给索引存储提供HA,我们建议将Atlas配置为使用Solr或Elasticsearch作为JanusGraph的索引存储支撑。 4.1 Solr要将Atlas配置为在HA模式下使用Solr,请执行以下操作: 选择HA模式下的现有SolrCloud群集设置以在Atlas中配置(OR)设置新的SolrCloud群集。 确保Solr在至少2个物理主机上启用以实现冗余,并且每个主机都运行Solr节点。 建议将冗余数量设置为至少2个副本。 创建Atlas所需的SolrCloud集合,详见Atlas官网“Installation Steps”。 有关在atlas.properties中配置以使用Solr设置Atlas的选项,请参阅我翻译的《Atlas开发指南(中文版)》的文档中“配置”章节。 4.2 Elasticsearch要将Atlas配置为在HA模式下使用Elasticsearch,请执行以下操作: 选择现有的Elasticsearch集群设置,(或)设置新的集群Elasticsearch集群。 确保Elasticsearch在至少五个物理主机上启用以实现冗余。 建议设置分片数量为3 有关在atlas.properties中配置以使用Elasticsearch设置Atlas的选项,请参阅我翻译的《Atlas开发指南(中文版)》的文档中“配置”章节。 5. 通知服务来自Hook的元数据通知事件通过写入名为ATLAS_HOOK的Kafka Topic发送到Atlas。同样,从Atlas到其他集成组件(如Ranger)的事件也会写入名为ATLAS_ENTITIES的Kafka Topic。由于Kafka持久化这些消息,即使消费者因发送事件而关闭,事件也不会丢失。此外,我们建议Kafka也设置容错,以便它具有更高的可用性保证。要将Atlas配置为在HA模式下使用Kafka,请执行以下操作: 选择在HA模式下设置的现有Kafka群集,以在Atlas(OR)中配置设置新的Kafka群集。 建议群集中不同的Kafka代理在不同的物理主机上使用Zookeeper进行协调,以提供Kafka的冗余和高可用性。 设置至少2个物理主机以实现冗余,每个主机托管一个Kafka代理。 为Atlas使用设置Kafka主题: ATLAS主题的分区数应设置为1(numPartitions) 确定Kafka主题的副本数量:将此设置为至少2以实现冗余。 运行以下命令:123$KAFKA_HOME/bin/kafka-topics.sh --create --zookeeper <list of zookeeper host:port entries> --topic ATLAS_HOOK --replication-factor <numReplicas> --partitions 1$KAFKA_HOME/bin/kafka-topics.sh --create --zookeeper <list of zookeeper host:port entries> --topic ATLAS_ENTITIES --replication-factor <numReplicas> --partitions 1Here KAFKA_HOME points to the Kafka installation directory. 在atlas-application.properties中,设置以下配置:123atlas.notification.embedded=falseatlas.kafka.zookeeper.connect=<comma separated list of servers forming Zookeeper quorum used by Kafka>atlas.kafka.bootstrap.servers=<comma separated list of Kafka broker endpoints in host:port form> - Give at least 2 for redundancy. 6. 问题如果托管Atlas表的HBase region servers挂掉,Atlas将无法存储或检索HBase中的元数据,直到它们重新联机。]]></content>
<categories>
<category>BigData</category>
<category>元数据管理</category>
</categories>
<tags>
<tag>元数据管理</tag>
<tag>atlas</tag>
<tag>血缘</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用Atlas进行元数据管理之Glossary(术语)]]></title>
<url>%2F%E4%BD%BF%E7%94%A8Atlas%E8%BF%9B%E8%A1%8C%E5%85%83%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86%E4%B9%8BGlossary(%E6%9C%AF%E8%AF%AD)%2F</url>
<content type="text"><![CDATA[背景:笔者和团队的小伙伴近期在进行数据治理/元数据管理方向的探索, 在接下来的系列文章中, 会陆续与读者们进行分享在此过程中踩过的坑和收获。 0. 当我们谈论数据治理/元数据管理的时候,我们究竟在讨论什么?谈到数据治理,自然离不开元数据。元数据(Metadata),用一句话定义就是:描述数据的数据。元数据打通了数据源、数据仓库、数据应用,记录了数据从产生到消费的全过程。因此,数据治理的核心就是元数据管理。 数据的真正价值在于数据驱动决策,通过数据指导运营。通过数据驱动的方法判断趋势,帮住我们发现问题,继而推动创新或产生新的解决方案。随着企业数据爆发式增长,数据体量越来越难以估量,我们很难说清楚我们到底拥有哪些数据,这些数据从哪里来,到哪里去,发生了什么变化,应该如何使用它们。因此元数据管理(数据治理)成为企业级数据湖不可或缺的重要组成部分。 可惜很长一段时间内,市面都没有成熟的数据治理解决方案。直到2015年,Hortonworks终于坐不住了,约了一众小伙伴公司倡议:咱们开始整个数据治理方案吧。然后,包含数据分类、集中策略引擎、数据血缘、安全和生命周期管理功能的Atlas应运而生。(PS:另一个应用的较多的元数据开源项目是Linkedin 在2016年新开源的项目:WhereHows)Atlas目前最新的版本为2018年9月18日发布的1.0.0版本。 1. Atlas介绍Atlas 是一个可伸缩和可扩展的核心基础治理服务集合 ,使企业能够有效地和高效地满足 Hadoop 中的合规性要求,并允许与整个企业数据生态系统的集成。 Apache Atlas为组织提供开放式元数据管理和治理功能,用以构建其数据资产目录,对这些资产进行分类和管理,并为数据科学家,数据分析师和数据治理团队提供围绕这些数据资产的协作功能。 关于Atlas的背景讲完了,接下来我们依次来讲Atlas中的几个概念,首先是今天的主角:Glossary。 1.1 Glossary(术语表) 介绍Atlas的术语表(Glossary)提供了一些适当的“单词”,这些“单词”能彼此进行关连和分类,以便业务用户在使用的时候,即使在不同的上下文中也能很好的理解它们。此外,这些术语也是可以映射到数据资产中的,比如:数据库,表,列等。 术语表抽象出了和数据相关的专业术语,使得用户能以他们更熟悉的方式去查找和使用数据。 1.2 术语表功能 能够使用自然语言(技术术语和/或业务术语)定义丰富的术语词汇表。 能够将术语在语义上相互关联。 能够将资产映射到术语表中。 能够按类别划分这些术语。这为术语增加了更多的上下文。 允许按层次结构排列类别,能展示更广泛和更精细的范围。 从元数据中独立管理术语表。 1.3 术语(Term)对于企业来说术语作用的非常大的。对于有用且有意义的术语,需要围绕其用途和上下文进行分组。 Apache Atlas中的术语必须具有唯一的qualifiedName,可以有相同名称的术语,但它们不能属于同一个术语表。具有相同名称的术语只能存在于不同的术语表中。 术语名称可以包含空格,下划线和短划线(作为引用单词的自然方式)但不包含“。”或“@”,因为qualifiedName的格式为:<术语>@<术语限定名>。限定名称可以更轻松地使用特定术语。 术语只能属于单个术语表,并且它们的生命周期也是相同的,如果删除术语表,则术语也会被删除。术语可以属于零个或多个类别,这允许将它们限定为更小或更大的上下文。 可以在Apache Atlas中为一个或多个实体分配/链接一个术语。可以使用分类(classifications,类似标签的作用)对术语进行分类,并将相同的分类应用于分配术语的实体。 1.4 类别(Category)类别是组织术语的一种方式,以便可以丰富术语的上下文。 类别可能包含也可能不包含层次结构,即子类别层次结构。类别的qualifiedName是使用它在术语表中的分层位置导出的,例如:<类别名称>.<父类别限定名>。当发生任何层级更改时,此限定名称都会更新,例如:添加父类别,删除父类别或更改父类别。 2. Atlas Web UIApache Atlas UI提供了友好的用户界面,可以使用术语表相关的功能,其中包括: 创建术语表,术语和类别 在术语之间创建各种关系: synonymns(同义词),antonymns(反义词),seeAlso(参考) 调整类别的层次结构中 为实体分配实体(entities) 使用关联术语搜索实体 与术语表相关的UI都可以在GLOSSARY的Tab下找到。 2.1 Glossary TabApache Atlas UI提供了两种使用术语表的方法: 术语(Terms)视图和类别(Category)视图。 (1) 术语视图(Terms)术语视图允许用户执行以下操作: 创建,更新和删除术语 添加,删除和更新与术语关联的分类 添加,删除和更新术语的分类 在术语之间创建各种关系 查看与术语关联的实体 (2) 类别视图(Category)类别视图允许用户执行以下操作: 创建,更新和删除类别和子类别 将术语与类别相关联 用户可以使用术语表选项卡中提供的切换在术语视图和类别视图之间切换。 2.2 术语视图(Terms) 创建一个新术语单击术语表名称旁边的省略号(…)会显示一个弹出式菜单,允许用户在术语表中创建术语或删除术语表 - 如下所示。 删除一个术语单击术语名称旁边的省略号(…)会显示一个弹出式菜单,允许用户删除该术语 - 如下所示。 2.2.1 术语详情选择术语表UI中的术语,可以查看对应术语的各种详细信息。详细信息页面下的每个选项卡提供该术语的不同详细信息。 Entities(实体)选项卡:显示分配给所选术语的实体 Classifications(分类)选项卡:显示与所选术语关联的分类 Related terms (相关术语)选项卡:显示与所选术语相关的术语 2.2.2 给术语添加分类(classification)单击分类标签旁边的+可为术语添加分类。 2.2.3 与其他术语建立术语关联查看术语详细信息时,单击Related Terms(相关术语)选项卡。单击+将术语与当前术语链接。 2.2.4 对术语进行分类单击类别标签旁边的+可对术语进行分类。将提供模态对话框以选择类别。 2.3 类别视图(Category)当切换开关处于Category时,左侧面板将列出所有术语表以及类别层次结构。 2.3.1 类别菜单(Category)单击Category旁边的省略号...将显示类别上下文菜单。 创建新类别 创建子类别或删除类别 2.3.2 类别详情选择Category后,详细信息将显示在右侧窗口中。 2.3.3 术语分类单击详情页中Terms标签旁边的+链接所选类别下的术语。 3. 术语分配流程可以在搜索结果页和Glossary-Terms实体详情页中给entity(实体)分配术语。 3.1 分配术语在搜索结果页面,点击terms列下的+ 点击terms标签旁边的+ 这两个操作都将显示下面的结果,按照屏幕上的提示完成术语分配。 3.2 分类传播(Propagated classification)如果一个术语具有分类,则该术语下的实体继承相同的分类。 3.3. 使用术语搜索Apache Atlas基本搜索API和UI已更新,以支持术语作为搜索条件。允许用户查找与给定术语相关联的实体。 4. REST APIAtlas支持以下操作,可在这里找到REST接口的详细信息。 5. JSON结构 Glossary 123456789101112131415161718192021222324252627282930313233343536373839404142{ "guid": "2f341934-f18c-48b3-aa12-eaa0a2bfce85", "qualifiedName": "SampleBank", "displayName": "Banking", "shortDescription": "Glossary of bank", "longDescription": "Glossary of bank - long description", "language": "English", "usage": "N/A", "terms": [ { "termGuid": "502d34f1-b85f-4ad9-9d9f-fe7020ff0acb", "relationGuid": "6bb803e4-3af6-4924-aad6-6ad9f95ecd14", "displayText": "A savings account" }, { "termGuid": "e441a540-ee55-4fc8-8eaf-4b9943d8929c", "relationGuid": "dbc46795-76ff-4f68-9043-be0eff0bc0f3", "displayText": "15-30 yr mortgage" }, { "termGuid": "998e3692-51a8-47fe-b3a0-0d9f794437eb", "relationGuid": "0dcd31b9-a81c-4185-ad4b-9209a97c305b", "displayText": "A checking account" }, { "termGuid": "c4e2b956-2589-4648-8596-240d3bea5e44", "relationGuid": "e71c4a5d-694b-47a5-a41e-126ade857279", "displayText": "ARM loans" }], "categories": [{ "categoryGuid": "dd94859e-7453-4bc9-b634-a17fc14590f8", "parentCategoryGuid": "e6a3df1f-5670-4f9e-84da-91f77d008ce3", "relationGuid": "a0b7da02-1ccd-4415-bc54-3d0cdb8857e7", "displayText": "Accounts" }, { "categoryGuid": "e6a3df1f-5670-4f9e-84da-91f77d008ce3", "relationGuid": "0e84a358-a4aa-4bd3-b806-497a6962ae1d", "displayText": "Customer" }, { "categoryGuid": "7f041401-de8c-443f-a3b7-7bf5a910ff6f", "parentCategoryGuid": "e6a3df1f-5670-4f9e-84da-91f77d008ce3", "relationGuid": "7757b031-4e25-43a8-bf77-946f7f06c67a", "displayText": "Loans" }]} Term 1234567891011121314151617181920212223242526272829303132{ "guid": "e441a540-ee55-4fc8-8eaf-4b9943d8929c", "qualifiedName": "fixed_mtg@SampleBank", "displayName": "15-30 yr mortgage", "shortDescription": "Short description", "longDescription": "Long description", "examples": ["N/A"], "abbreviation": "FMTG", "anchor": { "glossaryGuid": "2f341934-f18c-48b3-aa12-eaa0a2bfce85", "relationGuid": "dbc46795-76ff-4f68-9043-be0eff0bc0f3" }, "categories": [{ "categoryGuid": "7f041401-de8c-443f-a3b7-7bf5a910ff6f", "relationGuid": "b4cddd33-7b0c-41e2-9324-afe549ec6ada", "displayText": "Loans" }], "seeAlso" : [], "synonyms" : [], "antonyms" : [], "replacedBy" : [], "replacementTerms" : [], "translationTerms" : [], "translatedTerms" : [], "isA" : [], "classifies" : [], "preferredTerms" : [], "preferredToTerms": [ { "termGuid" : "c4e2b956-2589-4648-8596-240d3bea5e44", "displayText": "ARM Loans" }]} Category 123456789101112131415161718192021222324{ "guid": "7f041401-de8c-443f-a3b7-7bf5a910ff6f", "qualifiedName": "Loans.Customer@HortoniaBank", "displayName": "Loans", "shortDescription": "Loan categorization", "anchor": { "glossaryGuid": "2f341934-f18c-48b3-aa12-eaa0a2bfce85", "relationGuid": "7757b031-4e25-43a8-bf77-946f7f06c67a" }, "parentCategory": { "categoryGuid": "e6a3df1f-5670-4f9e-84da-91f77d008ce3", "relationGuid": "8a0a8e11-0bb5-483b-b7d6-cfe0b1d55ef6" }, "childrenCategories" : [], "terms": [{ "termGuid": "e441a540-ee55-4fc8-8eaf-4b9943d8929c", "relationGuid": "b4cddd33-7b0c-41e2-9324-afe549ec6ada", "displayText": "15-30 yr mortgage" }, { "termGuid": "c4e2b956-2589-4648-8596-240d3bea5e44", "relationGuid": "8db1e784-4f04-4eda-9a58-6c9535a95451", "displayText": "ARM loans" }]} 5.1 CURD(1)创建操作(CREATE) 创建术语表 创建一个术语 创建分类术语 用关系创建术语 创建一个类别 创建具有层次结构的类别 创建类别并对术语进行分类 为实体分配术语 注意: 在创建操作期间,术语表,术语和类别将获得自动分配的GUID和qualifiedName。 要创建包含子项的类别,必须事先创建子项。 要创建属于某个类别的术语,必须事先创建该类别。 要创建关系术语,必须事先创建相关术语。 (2)读操作(READ) 通过GUID获取术语表 - 提供属于术语表的所有术语和类别(标题)。 获取所有术语表 - 为所有术语表提供他们的术语和类别(标题)。 通过GUID获取术语 - 提供有关术语,其所属类别(如果有)以及任何相关术语的详细信息。 通过GUID获取类别 - 提供有关类别,类别层次结构(如果有)和属于该类别的术语的详细信息。 获取给定术语表的所有术语 - 提供属于给定术语表的所有术语(具有#3中提到的详细信息)。 获取给定术语表的所有类别 - 提供属于给定术语表的所有类别(具有#4中提到的详细信息)。 获取与给定术语相关的所有术语 - 提供与给定术语相关/链接的所有术语。 获取与给定类别(父母和子女)相关的所有类别 获取给定类别的所有条款 (3)更新操作(UPDATE) 局部更新术语表 局部更新术语 局部更新类别 更新给定的词汇表 更新给定的术语 更新给定的类别 注意: 局部更新仅处理词汇表模型文件中定义的原始属性。 分配后,无法更改GUID和qualifiedName。唯一的方法是删除并重新创建所需的对象。 在任何更新中都无法删除锚点 更新API期望在GET调用之后就地修改JSON。任何缺失的属性/关系都将被删除。 对类别层次结构的任何更新都会导致对其下的层次结构进行级联更新,例如锚更改会影响所有子项,父项更改会影响self和children的qualifiedName。 (4)删除操作(DELETE) 删除术语表 - 删除锚定到给定词汇表的所有类别和术语。如果已为实体分配任何术语,则会阻止此删除。 删除术语 - 仅当术语未与任何实体关联/分配时才删除该术语。 删除类别 - 仅删除给定类别,所有子项都成为顶级类别。 从实体中删除术语分配]]></content>
<categories>
<category>BigData</category>
<category>元数据管理</category>
</categories>
<tags>
<tag>元数据管理</tag>
<tag>atlas</tag>
<tag>血缘</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[大数据安全]基于Kerberos的大数据安全方案]]></title>
<url>%2F%5B%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%5D%E5%9F%BA%E4%BA%8EKerberos%E7%9A%84%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%E6%96%B9%E6%A1%88%2F</url>
<content type="text"><![CDATA[1.背景互联网从来就不是一个安全的地方。很多时候我们过分依赖防火墙来解决安全的问题,不幸的是,防火墙是假设“坏人”是来自外部的,而真正具有破坏性的攻击事件都是往往都是来自于内部的。 近几年,在thehackernews等网站上总会时不时的看到可以看到一些因为数据安全问题被大面积攻击、勒索的事件。在Hadoop1.0.0之前,Hadoop并不提供对安全的支持,默认集群内所有角色都是可靠的。用户访问时不需要进行任何验证,导致恶意用户很容易就可以伪装进入集群进行破坏。 要保证Hadoop集群的安全,至少要做到2个A:Authentication(认证),Authorization(授权)。常见的方案有: Authentication:MIT Kerberos, Azure AD, Kerby Authorization:Apache Sentry(Cloudera), Apache Ranger(Hortonworks) Hadoop集群对Kerberos的支持2012年1.0.0版本正式发布后,Hadoop才增加了对Kerberos的支持, 使得集群中的节点是可信任的。 Kerberos可以将认证的密钥在集群部署时事先放到可靠的节点上。集群运行时,集群内的节点使用密钥得到认证,认证通过后的节点才能提供服务。企图冒充的节点由于没有事先得到的密钥信息,无法与集群内部的节点通信。这样就防止了恶意地使用或篡改Hadoop集群的问题,确保了Hadoop集群的可靠性、安全性。 2.Kerberos介绍Kerberos是种网络身份验证协议,最初设计是用来保护雅典娜工程的网络服务器。Kerberos这个名字源于希腊神话,是一只三头犬的名字,它旨在通过使用密钥加密技术为Client/Server序提供强身份验证。可以用于防止窃听、防止重放攻击、保护数据完整性等场合,是一种应用对称密钥体制进行密钥管理的系统。Kerberos的扩展产品也使用公开密钥加密方法进行认证。 Kerberos目前最新版本是5,1~3版本只在MIT内部发行,因为使用DES加密,早期被美国出口管制局列为军需品禁止出口,直到瑞典皇家工学院实现了Kerberos版本4,KTH-KRB。后续也是这个团队实现了版本5: Heimdal,目前常见的Kerberos5实现之一。 本文中讨论的Kerberos5实现版本为MIT Kerberos,MIT保持的大约半年左右一次的更新速度,目前最新版本是2018-11-01发布的1.16.2版本。 2.1 名词解释 AS(Authentication Server):认证服务器 KDC(Key Distribution Center):密钥分发中心 TGT(Ticket Granting Ticket):票据授权票据,票据的票据 TGS(Ticket Granting Server):票据授权服务器 SS(Service Server):特定服务提供端 Principal:被认证的个体 Ticket:票据,客户端用来证明身份真实性。包含:用户名,IP,时间戳,有效期,会话秘钥。 使用Kerberos时,一个客户端需要经过三个步骤来获取服务: 认证: 客户端向认证服务器发送一条报文,获取一个包含时间戳的TGT。 授权: 客户端使用TGT向TGS请求指定Service的Ticket。 服务请求: 客户端向指定的Service出示服务Ticket鉴权通讯。 Kerberos协议在网络通信协定中属于显示层。其通信流程简单地说,用户先用共享密钥从某认证服务器得到一个身份证明。随后,用户使用这个身份证明与SS通信,而不使用共享密钥。 2.2 具体通信流程 ①此流程使用了对称加密; ②此流程发生在某一个Kerberos领域中; ③小写字母c,d,e,g是客户端发出的消息,大写字母A,B,E,F,H是各个服务器发回的消息。 首先,用户使用客户端上的程序进行登录: 输入用户ID和密码到客户端(或使用keytab登录)。 客户端程序运行一个单向函数(大多数为Hash)把密码转换成密钥,这个就是客户端的“用户密钥”(user’s secret key)。 2.2.1 客户端认证(Kinit)客户端(Client)从认证服务器(AS)获取票据的票据(TGT)。 Client向AS发送1条明文消息,申请基于该用户所应享有的服务,例如“用户Sunny想请求服务”(Sunny是用户ID)。(注意:用户不向AS发送“用户密钥”(user’s secret key),也不发送密码)该AS能够从本地数据库中查询到该申请用户的密码,并通过相同途径转换成相同的“用户密钥”(user’s secret key)。 AS检查该用户ID是否在于本地数据库中,如果用户存在则返回2条消息: 【消息A】:Client/TGS会话密钥(Client/TGS Session Key)(该Session Key用在将来Client与TGS的通信(会话)上),通过 用户密钥(user’s secret key) 进行加密。 【消息B】:票据授权票据(TGT)(TGT包括:消息A中的“Client/TGS会话密钥”(Client/TGS Session Key),用户ID,用户网址,TGT有效期),通过TGS密钥(TGS’s secret key) 进行加密。 一旦Client收到消息A和消息B,Client首先尝试用自己的“用户密钥”(user’s secret key)解密消息A,如果用户输入的密码与AS数据库中的密码不符,则不能成功解密消息A。输入正确的密码并通过随之生成的”user’s secret key”才能解密消息A,从而得到“Client/TGS会话密钥”(Client/TGS Session Key)。(注意:Client不能解密消息B,因为B是用TGS密钥(TGS’s secret key)加密的)。拥有了“Client/TGS会话密钥”(Client/TGS Session Key),Client就足以通过TGS进行认证了。 2.2.2 服务授权 Client从TGS获取票据(client-to-server ticket)。 当client需要申请特定服务时,其向TGS发送以下2条消息: 【消息c】:即消息B的内容(TGS’s secret key加密后的TGT),和想获取的服务的服务ID(注意:不是用户ID)。 【消息d】:认证符(Authenticator)(Authenticator包括:用户ID,时间戳),通过Client/TGS会话密钥(Client/TGS Session Key)进行加密。 收到消息c和消息d后,TGS首先检查KDC数据库中是否存在所需的服务,查找到之后,TGS用自己的“TGS密钥”(TGS’s secret key)解密消息c中的消息B(也就是TGT),从而得到之前生成的“Client/TGS会话密钥”(Client/TGS Session Key)。TGS再用这个Session Key解密消息d得到包含用户ID和时间戳的Authenticator,并对TGT和Authenticator进行验证,验证通过之后返回2条消息: 【消息E】:client-server票据(client-to-server ticket)(该ticket包括:Client/SS会话密钥 (Client/Server Session Key),用户ID,用户网址,有效期),通过提供该服务的服务器密钥(service’s secret key) 进行加密。 【消息F】:Client/SS会话密钥( Client/Server Session Key) (该Session Key用在将来Client与Server Service的通信(会话)上),通过Client/TGS会话密钥(Client/TGS Session Key) 进行加密。 Client收到这些消息后,用“Client/TGS会话密钥”(Client/TGS Session Key)解密消息F,得到“Client/SS会话密钥”(Client/Server Session Key)。(注意:Client不能解密消息E,因为E是用“服务器密钥”(service’s secret key)加密的)。 2.2.3 服务请求 Client从SS获取服务。 当获得“Client/SS会话密钥”(Client/Server Session Key)之后,Client就能够使用服务器提供的服务了。Client向指定服务器SS发出2条消息: 【消息e】:即上一步中的消息E“client-server票据”(client-to-server ticket),通过服务器密钥(service’s secret key) 进行加密 【消息g】:新的Authenticator(包括:用户ID,时间戳),通过Client/SS会话密钥(Client/Server Session Key) 进行加密 SS用自己的密钥(service’s secret key)解密消息e从而得到TGS提供的Client/SS会话密钥(Client/Server Session Key)。再用这个会话密钥解密消息g得到Authenticator,(同TGS一样)对Ticket和Authenticator进行验证,验证通过则返回1条消息(确认函:确证身份真实,乐于提供服务)。 【消息H】:新时间戳(新时间戳是:Client发送的时间戳加1,v5已经取消这一做法),通过Client/SS会话密钥(Client/Server Session Key) 进行加密。 Client通过Client/SS会话密钥(Client/Server Session Key)解密消息H,得到新时间戳并验证其是否正确。验证通过的话则客户端可以信赖服务器,并向服务器(SS)发送服务请求。 服务器(SS)向客户端提供相应的服务。 3.Kerberos HA架构Kerberos支持两种服务器在域内冗余方式:Master/Slave(MIT和Heimdal)和Multimaster结构(Windows Active Directory)。在生产环境中部署Kerberos时,最好使用一主(Master)多从(Slave)的架构,以确保Kerberos服务的高可用性。 Kerberos中每个KDC都包含数据库的副本。主KDC包含域(Realm)数据库的可写副本,它以固定的时间间隔复制到从KDC中。所有数据库更改(例如密码更改)都在主KDC上进行,当主KDC不可用时,从KDC提供Kerberos票据给服务授权,但不提供数据库管理。KDC需要一个Admin来进行日常的管理操作。 Kerberos的同步机制只复制主数据库的内容,但不传递配置文件,以下文件必须手动复制到每个Slave中:1234- krb5.conf- kdc.conf- kadm5.acl- master key stash file 3.1 HA方案目前单机房HA方案使用的较多的是Keepalived + Rsync 。Keepalived可以将多个无状态的单点通过虚拟IP(以下称为VIP)漂移的方式搭建成一个高可用服务。 首先,在Master KDC中创建数据库的dump文件(将当前的Kerberos和KADM5数据库转储为ASCII文件):1kdb5_util dump [-b7|-ov|-r13] [-verbose] [-mkey_convert] [-new_mkey_file mkey_file] [-rev] [-recurse] [filename [principals...]] 然后使用Rsync将目录同步到Slave机器的对应目录中,再导入KDC中:1kdb5_util load [-b7|-ov|-r13] [-hash] [-verbose] [-update] filename [dbname] Hadoop所有请求通过请求内网域名,解析到Keepalived绑定的VIP的方式来使用KDC: 4. 优化和展望4.1 优化(1)用户(Principal)管理如果团队中已经有一套权限系统,要将现有的身份系统集成到Kerberos中会很困难。随着业务的飞速增长,服务器规模越来越大,Kerberos Principal手动操作会越来越频繁,手动的增删改查维护会非常痛苦。需要在Kerberos管理系统中规范Principal申请、维护、删除、keytab生成流程。Principal申请和权限管理自动化。 (2)数据同步优化Kerberos数据同步可以将生成的数据记录同步写入到MySQL中,使用MySQL双主同步方式。在跨机房环境中,KDC数据使用Rsync工具进行增量同步。以A核心机房作为主机房,Rsync Server使用了Keepalived VIP的方式,当Kerberos主机宕机后,VIP漂移到另外一台主机器上,Rsync Client会以VIP所在的KDC主机器为Rsync Server进行数据同步,以保证KDC数据同步的高可用性。 (3)运维使用进程管理工具对Kerberos相关进程进行存活监控,当发现有进程异常退出时,邮件/微信/钉钉报警,主动再次拉起进程。 4.2 展望部署过Kerberos的同学都知道,在Hadoop集群部署Kerberos实际是一项非常繁琐的工作。Kerberos本质上是一种协议或安全通道,对于大多数用户或普通用户来说,是有一定学习曲线的,是否有更好的实现能够对普通用户隐藏这些繁琐的细节。 阿里和Intel合作项目Hadoop Authentication Service (HAS) 据称目前已经应用到ApsaraDB for HBase2.0中: HAS方案使用Kerby替代MIT Kerberos服务,利用HAS插件式验证方式建立一套人们习惯的账户密码体系。 目前HAS在Apache Kerby项目has-project分支开发中,未来会作为Kerbby的新feature出现在下一次release中。 Apache Kerby作为Apache Directory的一个子项目,目前关注度并不高,让我们期待它在后续的发展吧。]]></content>
<categories>
<category>BigData</category>
<category>安全</category>
</categories>
<tags>
<tag>大数据安全</tag>
<tag>Keberos</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[大数据安全]CDH集群禁用Kerberos]]></title>
<url>%2F%5B%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%5DCDH%E9%9B%86%E7%BE%A4%E7%A6%81%E7%94%A8Kerberos%2F</url>
<content type="text"><![CDATA[在调试Kerberos的时候可能会有需要禁用的场景。以下是各组件禁用Kerberos的相关配置。 环境 CDH版本:5.11.2 Linux版本:7.4.1708 Docker版本:Docker version 18.06.0-ce JDK版本:1.8 Zookeeper enableSecurity (Enable Kerberos Authentication) : false zoo.cfg 的Server 高级配置代码段(安全阀)写入skipACL: yes HDFS hadoop.security.authentication : Simple hadoop.security.authorization : false dfs.datanode.address : 1004 (for Kerberos) 改为 50010 (default) dfs.datanode.http.address : 1006 (for Kerberos) 改为 50075 (default) dfs.datanode.data.dir.perm : 700 改为 755 HBase hbase.security.authentication : Simple hbase.security.authorization : false hbase.thrift.security.qop : none Hue Kerberos Ticket Renewer: 删除或停用角色 Kafka kerberos.auth.enable: false SOLR solr Secure Authentication : Simple 参考资料: [1]Cloudera Manager Community : http://community.cloudera.com/t5/Cloudera-Manager-Installation/Disabling-Kerberos/td-p/19654]]></content>
<categories>
<category>BigData</category>
<category>安全</category>
</categories>
<tags>
<tag>Kerberos</tag>
<tag>大数据安全</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[大数据安全]Kerberos集群安装配置]]></title>
<url>%2F%5B%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%5DKerberos%E9%9B%86%E7%BE%A4%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE%2F</url>
<content type="text"><![CDATA[1. 概述Kerberos是一种计算机网络认证协议,它允许某实体在非安全网络环境下通信,向另一个实体以一种安全的方式证明自己的身份。它也指由麻省理工实现此协议,并发布的一套免费软件。它的设计主要针对客户-服务器模型,并提供了一系列交互认证——用户和服务器都能验证对方的身份。Kerberos协议可以保护网络实体免受窃听和重复攻击。 Kerberos协议基于对称密码学,并需要一个值得信赖的第三方。Kerberos协议的扩展可以为认证的某些阶段提供公钥密码学支持。 2. 环境说明: CDH版本:5.11.2 Linux版本:Centos 7 Docker版本:Docker version 18.06.0-ce JDK版本:1.8 操作用户:root 机器部署: # IP 主机名 Server Client 1 192.168.101.232 cdh-server-1 N/A Kerberos client 2 192.168.101.233 cdh-node-1 Kerberos server N/A 3 192.168.101.234 cdh-node-2 N/A Kerberos client 4 192.168.101.235 cdh-node-3 N/A Kerberos client 各节点之间可以通过ssh免密码登录Kerberos服务器和客户之间的时间同步 3. Kerberos 安装cdh-node-1作为Kerberos主节点安装服务:1yum install krb5-libs krb5-server krb5-workstation 通过命令查看安装列表rpm -qa|grep krb5: 123456[root@cdh-node-1 /]# rpm -qa | grep krb5krb5-workstation-1.15.1-19.el7.x86_64krb5-devel-1.15.1-19.el7.x86_64krb5-server-1.15.1-19.el7.x86_64krb5-libs-1.15.1-19.el7.x86_64[root@cdh-node-1 /]# 4. 配置kdc服务器包含三个配置文件:123456# 集群上所有节点都有这个文件而且内容同步/etc/krb5.conf# 主服务器上的kdc配置/var/kerberos/krb5kdc/kdc.conf# 能够不直接访问 KDC 控制台而从 Kerberos 数据库添加和删除主体,需要添加配置/var/kerberos/krb5kdc/kadm5.acl 1. 首先配置/etc/krb5.conf文件:1234567891011121314151617181920212223[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log[libdefaults] default_realm = EXAMPLE.COM #此处需要进行配置,把默认的EXAMPLE.COM修改为自己要定义的值 dns_lookup_kdc = false dns_lookup_realm = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true default_tgs_enctypes = rc4-hmac default_tkt_enctypes = rc4-hmac permitted_enctypes = rc4-hmac udp_preference_limit = 1 kdc_timeout = 3000[realms] EXAMPLE.COM = { kdc = cdh-node-1 #此处配置的为主机名 admin_server = cdh-node-1 #同上 } 配置项说明:更多参数设置请参考:官方文档。 以下是几个核心参数的说明: [logging]:日志输出设置 (可选) [libdefaults]:连接的默认配置 default_realm:Kerberos应用程序的默认领域,所有的principal都将带有这个领域标志 ticket_lifetime: 表明凭证生效的时限,一般为24小时 renew_lifetime: 表明凭证最长可以被延期的时限,一般为一个礼拜。当凭证过期之后,对安全认证的服务的后续访问则会失败 clockskew:时钟偏差是不完全符合主机系统时钟的票据时戳的容差,超过此容差将不接受此票据。通常,将时钟扭斜设置为 300 秒(5 分钟)。这意味着从服务器的角度看,票证的时间戳与它的偏差可以是在前后 5 分钟内 udp_preference_limit= 1:禁止使用 udp 可以防止一个 Hadoop 中的错误 default_ccache_name:credential缓存名,默认值为 [realms]:列举使用的 realm kdc:代表要 kdc 的位置。格式是 机器:端口 admin_server:代表 admin 的位置。格式是 机器:端口 default_domain:代表默认的域名 [domain_realm]:域名到realm的关系 (可选) 2.配置/var/kerberos/krb5kdc/kdc.conf文件 此处为EXAMPLE.COM与/etc/krb5.conf中的配置保持一致。1234567891011121314[kdcdefaults] kdc_ports = 88 kdc_tcp_ports = 88[realms] EXAMPLE.COM = { #master_key_type = aes256-cts acl_file = /var/kerberos/krb5kdc/kadm5.acl dict_file = /usr/share/dict/words admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal max_life = 1d max_renewable_life = 7d } 配置项说明:1234567- `kdcdefaults`:kdc相关配置,这里只设置了端口信息- `realms`:realms的配置 - `EXAMPLE.COM`:设定的realms领域 - `master_key_type`:和 supported_enctypes 默认使用 aes256-cts。JAVA 使用 aes256-cts 验证方式需要安装 JCE包(推荐不使用) - `acl_file`:标注了 admin 的用户权限,文件格式是:Kerberos_principal permissions [target_principal] [restrictions] - `supported_enctypes`:支持的校验方式 - `admin_keytab`:KDC 进行校验的 keytab 关于AES-256加密:对于使用 Centos5.6 及以上的系统,默认使用 AES-256来加密的。这就需要集群中的所有节点上安装 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy File下载的文件是一个 zip 包,解开后,将里面的两个文件放到下面的目录中:$JAVA_HOME/jre/lib/security 3. 创建/var/kerberos/krb5kdc/kadm5.acl内容为:`*/[email protected] 代表名称匹配/admin@EXAMPLE COM` 都认为是admin,权限是 代表全部权限。在KDC上我们需要编辑acl文件来设置权限,该acl文件的默认路径是 /var/kerberos/krb5kdc/kadm5.acl(也可以在文件kdc.conf中修改)。 Kerberos的kadmind daemon会使用该文件来管理对Kerberos database的访问权限。对于那些可能会对pincipal产生影响的操作,acl文件也能控制哪些principal能操作哪些其他pricipals。 4. 创建Kerberos数据库此步可能用时较长,创建完成会在/var/kerberos/krb5kdc/下面生成一系列文件。并且会提示输入数据库管理员的密码。1/usr/sbin/kdb5_util create -r EXAMPLE.COM –s # 此处为EXAMPLE.COM与/etc/krb5.conf中的配置保持一致。 [-s]:表示生成stash file,并在其中存储master server key(krb5kdc); [-r]:指定一个realm name —— 当krb5.conf中定义了多个realm时才是必要的。 如果需要重建数据库,将/var/kerberos/krb5kdc目录下的principal相关的文件删除即可. 当Kerberos database创建好后,可以看到目录 /var/kerberos/krb5kdc 下生成了几个文件: 123456kadm5.aclkdc.confprincipalprincipal.kadm5principal.kadm5.lockprincipal.ok 5. 添加database administrator为Kerberos database添加administrative principals (即能够管理database的principals) —— 至少要添加1个principal来使得Kerberos的管理进程kadmind能够在网络上与程序kadmin进行通讯。 创建管理员并输入密码admin。kadmin.local可以直接运行在KDC上,而无需通过Kerberos认证。 为用户设置密码: 123456[root@cdh-node-1 /]# kadmin.local -q "addprinc admin/admin"Authenticating as principal root/[email protected] with password.WARNING: no policy specified for admin/[email protected]; defaulting to no policyEnter password for principal "admin/[email protected]":Re-enter password for principal "admin/[email protected]": Principal "admin/[email protected]" created. 6. 设置kerberos服务为开机启动,关闭防火墙123chkconfig krb5kdc onchkconfig kadmin onchkconfig iptables off 7. 启动krb5kdc和kadmind进程12/usr/sbin/kadmind/usr/sbin/krb5kdc 或123service krb5kdc startservice kadmin startservice krb5kdc status 现在KDC已经在工作了。这两个daemons将会在后台运行,可以查看它们的日志文件(/var/log/krb5kdc.log 和 /var/log/kadmind.log)。 8. 检查Kerberos正常运行1kinit admin/admin 9. 集群中的其他主机安装Kerberos Client1yum install krb5-workstation krb5-libs krb5-auth-dialog 配置这些主机上的/etc/krb5.conf,这个文件的内容与KDC中的文件保持一致即可。 10. 在cm节点安装ldap客户端1yum install openldap-clients 5. Kerberos使用常用命令: 123456789kinit admin/[email protected] # 初始化证书klist # 查看当前证书kadmin.local -q "list_principals" # 列出Kerberos中的所有认证用户kadmin.local -q "addprinc user1" # 添加认证用户,需要输入密码kinit user1 # 使用该用户登录,获取身份认证,需要输入密码klist # 查看当前用户的认证信息ticketkinit –R # 更新ticketkdestroy # 销毁当前的ticketkadmin.local -q "delprinc user1" # 删除认证用户 5.1 管理员使用1. 登录登录到管理员账户,如果在本机上,可以通过kadmin.local直接登录: 123[root@cdh-node-1 /]# kadmin.localAuthenticating as principal root/[email protected] with password.kadmin.local: 其它机器的,先使用kinit进行验证: 123456[root@cdh-server-1 /]# kinit admin/adminPassword for admin/[email protected]:[root@cdh-server-1 /]# kadminAuthenticating as principal admin/[email protected] with password.Password for admin/[email protected]:kadmin: 2. 增删改查账户在管理员的状态下使用addprinc,delprinc,modprinc,listprincs命令。使用?可以列出所有的命令。1234567891011[root@cdh-node-1 /]# kadmin.localAuthenticating as principal root/[email protected] with password.kadmin.local: delprinc testAre you sure you want to delete the principal "[email protected]"? (yes/no): yesPrincipal "[email protected]" deleted.Make sure that you have removed this principal from all ACLs before reusing.kadmin.local: listprincsHTTP/[email protected]/[email protected]/[email protected]... 3. 生成keytab:使用xst命令或者ktadd命令1[root@cdh-node-1 /]# kadmin:xst -k /xxx/xxx/kerberos.keytab hdfs/hadoop1 5.2 用户使用1. 查看当前认证用户123456[root@cdh-node-2 /]# klistTicket cache: FILE:/tmp/krb5cc_0Default principal: [email protected] starting Expires Service principal08/08/2018 17:49:41 08/09/2018 17:49:41 krbtgt/[email protected] 2. 认证用户1[root@cdh-node-2 /]# kinit -kt /xx/xx/kerberos.keytab hdfs/hadoop1 3. 删除当前的认证的缓存123[root@cdh-node-2 /]# kdestroy[root@cdh-node-2 /]# klistklist: No credentials cache found (filename: /tmp/krb5cc_0) 6. 一些概念1. PrincipalKerberos principal用于在kerberos加密系统中标记一个唯一的身份。kerberos为kerberos principal分配tickets使其可以访问由kerberos加密的hadoop服务。对于hadoop,principals的格式为username/[email protected]. 2. Keytabkeytab是包含principals和加密principal key的文件。keytab文件对于每个host是唯一的,因为key中包含hostname。keytab文件用于不需要人工交互和保存纯文本密码,实现到kerberos上验证一个主机上的principal。因为服务器上可以访问keytab文件即可以以principal的身份通过kerberos的认证,所以,keytab文件应该被妥善保存,应该只有少数的用户可以访问。]]></content>
<categories>
<category>BigData</category>
<category>安全</category>
</categories>
<tags>
<tag>Kerberos</tag>
<tag>大数据安全</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[大数据安全]Apache Kylin 安全配置(Kerberos)]]></title>
<url>%2F%5B%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%5DApache%20Kylin%20%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE(Kerberos)%2F</url>
<content type="text"><![CDATA[1. 概述本文首先会简单介绍Kylin的安装配置,然后介绍启用Kerberos的CDH集群中如何部署及使用Kylin。 Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发并贡献至开源社区。它能在亚秒内查询巨大的Hive表。 1.2 环境说明 CDH版本:5.11.2 Linux版本:7.4.1708 Docker版本:Docker version 18.06.0-ce JDK版本:1.8 操作用户:root 2.Kylin安装配置2.1 安装此处以Kylin 2.0.0版本为例。社区版Kylin地址:https://archive.apache.org/dist/kylin/ 12345[root@node-3 ~]# cd /usr/local/src/[root@node-3 src]# wget https://archive.apache.org/dist/kylin/apache-kylin-2.0.0/apache-kylin-2.0.0-bin-cdh57.tar.gz[root@node-3 src]# tar xf apache-kylin-2.0.0-bin-cdh57.tar.gz[root@node-3 src]# cp -a apache-kylin-2.0.0-bin /usr/local/[root@node-3 src]# ln -s /usr/local/apache-kylin-2.0.0-bin /usr/local/kylin 2.2 环境配置1234567891011export BASE_PATH_BIG=/opt/cloudera/parcels/CDH/lib#added by Hbaseexport HBASE_HOME=$BASE_PATH_BIG/hbase#added by HCatexport HCAT_HOME=/opt/cloudera/parcels/CDH/lib/hive-hcatalog/share/hcatalog#added by Kylinexport KYLIN_HOME=/usr/local/kylinexport PATH=$HBASE_HOME/bin:$PATH 然后执行source /etc/profile生效。 2.3 Kylin配置编辑/usr/local/kylin/conf/kylin.properites文件,新增以下配置: Kylin2.0+版本配置的名称有变化,具体参考:https://github.com/apache/kylin/blob/2.0.x/core-common/src/main/resources/kylin-backward-compatibility.properties 123456789## 修改配置(替换地址)kylin.rest.servers=192.168.100.102:7070## 新增配置kylin.job.jar=/usr/local/apache-kylin-2.0.0-bin/lib/kylin-job-2.0.0.jarkylin.coprocessor.local.jar=/usr/local/apache-kylin-2.0.0-bin/lib/kylin-coprocessor-2.0.0.jar## 替换地址kylin.job.yarn.app.rest.check.status.url=http://cdh-node-2:8088/ws/v1/cluster/apps/${job_id}?anonymous=truekylin.job.mr.lib.dir=/opt/cloudera/parcels/CDH-5.11.2-1.cdh5.11.2.p0.4/lib/sentry/lib 配置说明: kylin.rest.servers:kylin实例服务器列表,注意:不包括以job模式运行的服务器实例! kylin.job.jar:MR jobs依赖 kylin.coprocessor.local.jar:Hbase协同处理依赖,用于提高性能。 kylin.job.yarn.app.rest.check.status.url:yarn工作区 kylin.job.mr.lib.dir:Hive/Hbase依赖目录。(在没有安装Hive/Hbase的节点上构建Cube会因为找不到依赖报ClassNotFoundException错误,需要此配置。具体参考这边博文《上传Kylin MR依赖》 )。 更多配置请参考官网配置指南。 2.4 创建用户在每个节点创建Kylin用户 1useradd kylin 3. Kerberos配置3.1 创建kylin账号在Kerberos server上创建kylin账号: 12345678[root@cdh-node-1 /]# kadmin.localAuthenticating as principal admin/[email protected] with password.kadmin.local: addprinc kylinWARNING: no policy specified for [email protected]; defaulting to no policyEnter password for principal "[email protected]":Re-enter password for principal "[email protected]":add_principal: Principal or policy already exists while creating "[email protected]".kadmin.local: 3.2 生成keytab文件生成kylin账号keytab文件:1xst -norandkey -k kylin.keytab [email protected] 将kylin.keytab复制到每个kylin节点上。 3.3 定时刷新kt在kylin节点上配置定时任务进行kinit命令: 1kinit -k -t /root/kylin.keytab [email protected] 添加定时任务,这里设置每天凌晨1点执行一次,可根据kerberos的过期时间自己配置。 编写shell脚本: 123[root@cdh-node-2 security]# cat init_kt.sh#!/bin/bashkinit -kt ./kylin.keytab [email protected] 添加定时任务: 12345678[root@cdh-node-2 security]# crontab -e# 添加以下内容0 1 * * * root /home/security/init_kt.sh > /tmp/kylin-ktinit.log 2>&1# 查看定时任务[root@cdh-node-2 security]# crontab -l0 1 * * * root /home/security/init_kt.sh > /tmp/kylin-ktinit.log 2>&1 3.4 添加Hive权限 登录Hive使用拥有操作hive权限的kerberos账户登录beeline: 1234567891011[root@cdh-node-3 hive]# beeline -u 'jdbc:hive2://cdh-node-3:10000/default;principal=hive/[email protected]'Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512M; support was removed in 8.0Java HotSpot(TM) 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future releaseJava HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512M; support was removed in 8.0scan complete in 2msConnecting to jdbc:hive2://cdh-node-3:10000/default;principal=hive/[email protected] to: Apache Hive (version 1.1.0-cdh5.11.2)Driver: Hive JDBC (version 1.1.0-cdh5.11.2)Transaction isolation: TRANSACTION_REPEATABLE_READBeeline version 1.1.0-cdh5.11.2 by Apache Hive0: jdbc:hive2://cdh-node-3:10000/default> 添加kylin权限将admin角色权限赋予kylin: 123456789100: jdbc:hive2://cdh-node-3:10000/default> grant role admin to user kylin;INFO : Compiling command(queryId=hive_20180914174141_6359e1a1-251f-4116-b646-0aa9f55dcfa8): grant role admin to user leiliINFO : Semantic Analysis CompletedINFO : Returning Hive schema: Schema(fieldSchemas:null, properties:null)INFO : Completed compiling command(queryId=hive_20180914174141_6359e1a1-251f-4116-b646-0aa9f55dcfa8); Time taken: 0.069 secondsINFO : Executing command(queryId=hive_20180914174141_6359e1a1-251f-4116-b646-0aa9f55dcfa8): grant role admin to user leiliINFO : Starting task [Stage-0:DDL] in serial modeINFO : Completed executing command(queryId=hive_20180914174141_6359e1a1-251f-4116-b646-0aa9f55dcfa8); Time taken: 0.331 secondsINFO : OKNo rows affected (0.528 seconds) 3.5 添加Hbase权限使用拥有操作hbase权限的kerberos账户登录hbase shell: 123456[root@cdh-node-3 hive]# hbase shellJava HotSpot(TM) 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release18/09/14 17:44:40 INFO Configuration.deprecation: hadoop.native.lib is deprecated. Instead, use io.native.lib.availableHBase Shell; enter 'help<RETURN>' for list of supported commands.Type "exit<RETURN>" to leave the HBase ShellVersion 1.2.0-cdh5.11.2, rUnknown, Fri Aug 18 14:09:37 PDT 2017 给kylin用户授权12base(main):001:0> grant 'kylin','RWXCA'0 row(s) in 0.5830 seconds 切换到kylin用户重新登录hbase shell,测试一下: 123456789101112hbase(main):001:0> [email protected] (auth:KERBEROS) groups: kylinhbase(main):002:0> create 'test', 'cf'0 row(s) in 2.6930 seconds=> Hbase::Table - testhbase(main):003:0> listTABLEtest1 row(s) in 0.0310 seconds 3.6 执行Kylin检查123[root@cdh-node-2 bin]# ./check-env.shRetrieving hadoop conf dir...KYLIN_HOME is set to /usr/local/apache-kylin-2.0.0-bin 3.7 启动kylin服务先确认主机使用kerberos凭据为kylin,再启动: 1234567891011121314151617181920[root@cdh-node-2 bin]# klistTicket cache: FILE:/tmp/krb5cc_0Default principal: [email protected] starting Expires Service principal09/14/2018 17:48:28 09/15/2018 17:48:28 krbtgt/[email protected] renew until 09/21/2018 17:48:28[root@cdh-node-2 bin]# ./kylin.sh startRetrieving hadoop conf dir...KYLIN_HOME is set to /usr/local/kylinRetrieving hive dependency...Retrieving hbase dependency...Retrieving hadoop conf dir...Retrieving kafka dependency...Retrieving Spark dependency...KYLIN_JVM_SETTINGS is -Xms1024M -Xmx4096M -Xss1024K -XX:MaxPermSize=128M -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/usr/local/kylin/logs/kylin.gc.3982 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=64MA new Kylin instance is started by root. To stop it, run 'kylin.sh stop'Check the log at /usr/local/kylin/logs/kylin.logWeb UI is at http://<hostname>:7070/kylin 4. 使用Kylin Sample测试Kylin本身自带了一个测试例子,创建流程如下:执行sample.sh脚本,这个主要是创建kylin的project、model、cube以及相关的hive表等。 12345678910[root@cdh-node-2 bin]# ./sample.shRetrieving hadoop conf dir...Retrieving hadoop conf dir...KYLIN_HOME is set to /usr/local/kylinLoading sample data into HDFS tmp path: /tmp/kylin/sample_cube/d...Sample cube is created successfully in project 'learn_kylin'.Restart Kylin server or reload the metadata from web UI to see the change. 进入Kylin Web界面system - reload metadata然后构建示例的cube,如果构建成功,并且能成功执行查询命令,则表示整个配置全部完成。 [1] Cloudera Configuring Authentication Doc: https://www.cloudera.com/documentation/enterprise/5-11-x/topics/sg_authentication.html[2] Kylin官网配置指南:http://kylin.apache.org/cn/docs/install/configuration.html[3] Linux下的crontab定时执行任务命令详解:https://www.cnblogs.com/longjshz/p/5779215.html]]></content>
<categories>
<category>BigData</category>
<category>安全</category>
</categories>
<tags>
<tag>Kerberos</tag>
<tag>大数据安全</tag>
<tag>Kylin</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习实战]决策树]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98%5D%E5%86%B3%E7%AD%96%E6%A0%91%2F</url>
<content type="text"><![CDATA[1. 简介 决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系。Entropy = 系统的凌乱程度,使用算法ID3, C4.5和C5.0生成树算法使用熵。这一度量是基于信息学理论中熵的概念。 决策树是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。 决策树学习通常包括 3 个步骤: 特征选择 决策树的生成 决策树的修剪 1.1 决策树场景场景一:二十个问题有一个叫 “二十个问题” 的游戏,游戏规则很简单:参与游戏的一方在脑海中想某个事物,其他参与者向他提问,只允许提 20 个问题,问题的答案也只能用对或错回答。问问题的人通过推断分解,逐步缩小待猜测事物的范围,最后得到游戏的答案。 场景二:邮件分类一个邮件分类系统,大致工作流程如下: 首先检测发送邮件域名地址。如果地址为 myEmployer.com, 则将其放在分类 “无聊时需要阅读的邮件”中。如果邮件不是来自这个域名,则检测邮件内容里是否包含单词 “曲棍球” , 如果包含则将邮件归类到 “需要及时处理的朋友邮件”,如果不包含则将邮件归类到 “无需阅读的垃圾邮件” 。 1.2 定义分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点(node)和有向边(directed edge)组成。 结点有两种类型: 内部结点(internal node):表示一个特征或属性。 叶结点(leaf: node):表示一个类。 用决策树分类,从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子结点;这时,每一个子结点对应着该特征的一个取值。如此递归地对实例进行测试并分配,直至达到叶结点。最后将实例分配到叶结点的类中。 2. 决策树原理 熵:熵(entropy)指的是体系的混乱的程度,在不同的学科中也有引申出的更为具体的定义,是各领域十分重要的参量。 信息熵(香农熵):是一种信息的度量方式,表示信息的混乱程度,也就是说:信息越有序,信息熵越低。例如:火柴有序放在火柴盒里,熵值很低,相反,熵值很高。 信息增益:在划分数据集前后信息发生的变化称为信息增益。 2.1 工作原理我们使用 createBranch() 方法构造一个决策树,如下所示: 123456789检测数据集中的所有数据的分类标签是否相同: If so return 类标签 Else: 寻找划分数据集的最好特征(划分之后信息熵最小,也就是信息增益最大的特征) 划分数据集 创建分支节点 for 每个划分的子集 调用函数 createBranch (创建分支的函数)并增加返回结果到分支节点中 return 分支节点 2.2 决策树开发流程1234561. 收集数据:可以使用任何方法。2. 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化。3. 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期。4. 训练算法:构造树的数据结构。5. 测试算法:使用经验树计算错误率。(经验树没有搜索到较好的资料,有兴趣的同学可以来补充)6. 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。 2.3 决策树算法特点 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。 缺点:可能会产生过度匹配问题。适用数据类型:数值型和标称型。 3. 实战案例3.1 项目概述根据以下 2 个特征,将动物分成两类:鱼类和非鱼类。 特征: 不浮出水面是否可以生存 是否有脚蹼 3.2 开发流程(1) 收集数据 可以使用任何方法 我们利用 createDataSet() 函数输入数据: 12345678def createDataSet(): dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] labels = ['no surfacing', 'flippers'] return dataSet, labels (2) 准备数据 树构造算法只适用于标称型数据,因此数值型数据必须离散化 此处,由于我们输入的数据本身就是离散化数据,所以这一步就省略了。 (3) 分析数据 可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期 计算给定数据集的香农熵的函数12345678910111213141516171819202122def calcShannonEnt(dataSet): # 求list的长度,表示计算参与训练的数据量 numEntries = len(dataSet) # 计算分类标签label出现的次数 labelCounts = {} # the the number of unique elements and their occurance for featVec in dataSet: # 将当前实例的标签存储,即每一行数据的最后一个数据代表的是标签 currentLabel = featVec[-1] # 为所有可能的分类创建字典,如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。 if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 # 对于 label 标签的占比,求出 label 标签的香农熵 shannonEnt = 0.0 for key in labelCounts: # 使用所有类标签的发生频率计算类别出现的概率。 prob = float(labelCounts[key])/numEntries # 计算香农熵,以 2 为底求对数 shannonEnt -= prob * log(prob, 2) return shannonEnt 按照给定特征划分数据集将指定特征的特征值等于 value 的行剩下列作为子数据集。 1234567891011121314151617181920212223242526272829303132333435363738394041def splitDataSet(dataSet, index, value): """splitDataSet(通过遍历dataSet数据集,求出index对应的colnum列的值为value的行) 就是依据index列进行分类,如果index列的数据等于 value的时候,就要将 index 划分到我们创建的新的数据集中 Args: dataSet 数据集 待划分的数据集 index 表示每一行的index列 划分数据集的特征 value 表示index列对应的value值 需要返回的特征的值。 Returns: index列为value的数据集【该数据集需要排除index列】 """ retDataSet = [] for featVec in dataSet: # index列为value的数据集【该数据集需要排除index列】 # 判断index列的值是否为value if featVec[index] == value: # chop out index used for splitting # [:index]表示前index行,即若 index 为2,就是取 featVec 的前 index 行 reducedFeatVec = featVec[:index] ''' 请百度查询一下: extend和append的区别 list.append(object) 向列表中添加一个对象object list.extend(sequence) 把一个序列seq的内容添加到列表中 1、使用append的时候,是将new_media看作一个对象,整体打包添加到music_media对象中。 2、使用extend的时候,是将new_media看作一个序列,将这个序列和music_media序列合并,并放在其后面。 result = [] result.extend([1,2,3]) print result result.append([4,5,6]) print result result.extend([7,8,9]) print result 结果: [1, 2, 3] [1, 2, 3, [4, 5, 6]] [1, 2, 3, [4, 5, 6], 7, 8, 9] ''' reducedFeatVec.extend(featVec[index+1:]) # [index+1:]表示从跳过 index 的 index+1行,取接下来的数据 # 收集结果值 index列为value的行【该行需要排除index列】 retDataSet.append(reducedFeatVec) return retDataSet 选择最好的数据集划分方式12345678910111213141516171819202122232425262728293031323334353637383940def chooseBestFeatureToSplit(dataSet): """chooseBestFeatureToSplit(选择最好的特征) Args: dataSet 数据集 Returns: bestFeature 最优的特征列 """ # 求第一行有多少列的 Feature, 最后一列是label列嘛 numFeatures = len(dataSet[0]) - 1 # 数据集的原始信息熵 baseEntropy = calcShannonEnt(dataSet) # 最优的信息增益值, 和最优的Featurn编号 bestInfoGain, bestFeature = 0.0, -1 # iterate over all the features for i in range(numFeatures): # create a list of all the examples of this feature # 获取对应的feature下的所有数据 featList = [example[i] for example in dataSet] # get a set of unique values # 获取剔重后的集合,使用set对list数据进行去重 uniqueVals = set(featList) # 创建一个临时的信息熵 newEntropy = 0.0 # 遍历某一列的value集合,计算该列的信息熵 # 遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。 for value in uniqueVals: subDataSet = splitDataSet(dataSet, i, value) # 计算概率 prob = len(subDataSet)/float(len(dataSet)) # 计算信息熵 newEntropy += prob * calcShannonEnt(subDataSet) # gain[信息增益]: 划分数据集前后的信息变化, 获取信息熵最大的值 # 信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。 infoGain = baseEntropy - newEntropy print 'infoGain=', infoGain, 'bestFeature=', i, baseEntropy, newEntropy if (infoGain > bestInfoGain): bestInfoGain = infoGain bestFeature = i return bestFeature Q:上面的 newEntropy 为什么是根据子集计算的呢?A :因为我们在根据一个特征计算香农熵的时候,该特征的分类值是相同,这个特征这个分类的香农熵为 0;这就是为什么计算新的香农熵的时候使用的是子集。 (4)训练算法 构造树的数据结构 创建树的函数代码如下: 12345678910111213141516171819202122232425262728293031def createTree(dataSet, labels): classList = [example[-1] for example in dataSet] # 如果数据集的最后一列的第一个值出现的次数=整个集合的数量,也就说只有一个类别,就只直接返回结果就行 # 第一个停止条件:所有的类标签完全相同,则直接返回该类标签。 # count() 函数是统计括号中的值在list中出现的次数 if classList.count(classList[0]) == len(classList): return classList[0] # 如果数据集只有1列,那么最初出现label次数最多的一类,作为结果 # 第二个停止条件:使用完了所有特征,仍然不能将数据集划分成仅包含唯一类别的分组。 if len(dataSet[0]) == 1: return majorityCnt(classList) # 选择最优的列,得到最优列对应的label含义 bestFeat = chooseBestFeatureToSplit(dataSet) # 获取label的名称 bestFeatLabel = labels[bestFeat] # 初始化myTree myTree = {bestFeatLabel: {}} # 注:labels列表是可变对象,在PYTHON函数中作为参数时传址引用,能够被全局修改 # 所以这行代码导致函数外的同名变量被删除了元素,造成例句无法执行,提示'no surfacing' is not in list del(labels[bestFeat]) # 取出最优列,然后它的branch做分类 featValues = [example[bestFeat] for example in dataSet] uniqueVals = set(featValues) for value in uniqueVals: # 求出剩余的标签label subLabels = labels[:] # 遍历当前选择特征包含的所有属性值,在每个数据集划分上递归调用函数createTree() myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels) # print 'myTree', value, myTree return myTree (5)测试算法 使用决策树执行分类代码如下: 1234567891011121314151617181920212223242526def classify(inputTree, featLabels, testVec): """classify(给输入的节点,进行分类) Args: inputTree 决策树模型 featLabels Feature标签对应的名称 testVec 测试输入的数据 Returns: classLabel 分类的结果值,需要映射label才能知道名称 """ # 获取tree的根节点对于的key值 firstStr = inputTree.keys()[0] # 通过key得到根节点对应的value secondDict = inputTree[firstStr] # 判断根节点名称获取根节点在label中的先后顺序,这样就知道输入的testVec怎么开始对照树来做分类 featIndex = featLabels.index(firstStr) # 测试数据,找到根节点对应的label位置,也就知道从输入的数据的第几位来开始分类 key = testVec[featIndex] valueOfFeat = secondDict[key] print '+++', firstStr, 'xxx', secondDict, '---', key, '>>>', valueOfFeat # 判断分枝是否结束: 判断valueOfFeat是否是dict类型 if isinstance(valueOfFeat, dict): classLabel = classify(valueOfFeat, featLabels, testVec) else: classLabel = valueOfFeat return classLabel (6)使用算法 此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。 构造决策树是很耗时的任务,即使很小的数据集也要花费几秒。如果用创建好的决策树解决分类问题就可以很快完成。 因此为了节省计算时间,最好能每次执行分类时调用已经构造好的决策树,为了解决这个问题,需要使用Python模块pickle序列化对象。序列化对象可以在磁盘上保存对象,并在需要的时候读取出来。任何对象都可以执行序列化,包括字典对象。 下面代码是使用pickle模块存储决策树: 12345678910def storeTree(inputTree, filename): impory pickle fw = open(filename, 'w') pickle.dump(inputTree, fw) fw.close()def grabTree(filename): import pickle fr = open(filename) return pickle.load(fr) 通过上面的代码我们可以把分类器存储在硬盘上,而不用每次对数据分类时重新学习一遍,这也是决策树的优点之一。++K-近邻算法就无法持久化分类器++。 [1] 决策树维基百科: https://zh.wikipedia.org/wiki/%E5%86%B3%E7%AD%96%E6%A0%91[2]《机器学习实战》 – Peter Harrington[3]《机器学习》 – 周志华]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
<tag>决策树</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习Lesson 4]多元线性回归]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0Lesson%204%5D%E5%A4%9A%E5%85%83%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92%2F</url>
<content type="text"><![CDATA[1. 多元线性回归定义在回归分析中,如果有两个或两个以上的自变量,就称为多元回归。事实上,一种现象常常是与多个因素相联系的,由多个自变量的最优组合共同来预测或估计因变量,比只用一个自变量进行预测或估计更有效,更符合实际。因此多元线性回归比一元线性回归的实用意义更大。我们现在介绍方程的符号,我们可以有任意数量的输入变量。 这些多个特征的假设函数的多变量形式如下: 1hθ(x)=θ0+θ1x1+θ2x2+θ3x3+⋯+θnxn 为了开发这个功能,我们可以想一想,θ0作为房子的基本价格,θ1每平方米的价格,θ2每层楼的价格,等X1将在房子的平方米数,x2楼层数,等等。 利用矩阵乘法的定义,我们的多变量假设函数可以简洁地表示为: 这是对一个训练例子的假设函数的矢量化。 备注:为了方便的原因,在这个过程中我们假设X(i)0 = 1(i∈1,…,m)。这允许我们做矩阵运算与θ和X使两向量的θ和X(i)互相匹配元素(即有相同数目的元素:N + 1)]。 2. 梯度下降下面我们使用梯度下降法来解决多特征的线性回归问题。 Hypothesis: 假设假设现有多元线性回归并约定x0=1。 Parameters: 该模型的参数是从θ0 到θn。不要认为这是 n+1 个单独的参数。你可以把这 n+1 个 θ 参数想象成一个 n+1 维的向量 θ。所以,现在就可以把这个模型的参数 想象成其本身就是一个 n+1 维的向量。 Cost function: 我们的代价函数是从 θ0 到 θn 的函数 J,并给出了误差项平方的和。但同样地,不要把函数 J想成是一个关于 n+1 个自变量的函数,而是看成带有一个 n+1 维向量的函数。 Gradient descent(梯度下降): 我们将会不停地用 θj 减去 α 倍的导数项,来替代 θj 同样的方法。我们写出函数J(θ) 因此 θj 被更新成 θj 减去学习率 α 与对应导数的乘积 就是代价函数的对参数 θj 的偏导数。 2.1 当特征 n=1 时 我们有两条针对参数 θ0 和 θ1 不同的更新规则。①处是代价函数里部分求导的结果 ,是代价函数相对于 θ0 的偏导数。 同样,对参数 θ1 我们有另一个更新规则 仅有的一点区别是:当我们之前只有一个特征,我们称该特征为x(i)。 但现在我们在新符号里,我们会标记它为 x 上标 (i) 下标1来表示我们的特征。以上就是当我们仅有一个特征时候的算法。 2.2 当有一个以上特征时 现有数目远大于1的很多特征,梯度下降更新规则变成了这样: 有些同学可能知道微积分,代价函数 J 对参数 θj 求偏导数 (蓝线圈出部分),你将会得到多元线性回归的梯度下降算法。 新旧两种算法实际上是两个是类似的算法。为什么它们都是梯度下降算法?考虑这样一个情况:有两个或以上个数的特征,同时我们对θ1、θ2、θ3的三条更新规则,当然可能还有其它参数。如果你观察θ0的更新规则,你会发现这跟之前 n=1的情况相同。它们之所以是等价的这是因为在我们的标记约定里有 x(i)0=1,),也就红线圈起部分的两项是等价的。 同样地,如果你观察θ1的更新规则你会发现这里的这一项是和之前对参数θ1的更新项是等价的。在这里我们只是用了新的符号x(i)1来表示我们的第一个特征。现在我们有个更多的特征,那么就可以用与之前相同的更新规则,我们可以用同样的规则来处理 θ2 等其它参数。 3. Feature Scaling(特征缩放)如果你有一个机器学习问题,这个问题有多个特征,如果你能确保这些特征都处在一个相近的范围,确保不同特征的取值在相近的范围内,这样梯度下降法就能更快地收敛。 3.1 介绍假如你有一个具有两个特征的问题:其中,x1是房屋面积大小,它的取值在0到2000之间。x2是卧室的数量,可能这个值取值范围在1到5之间。 如果你画出代价函数J(θ)的轮廓图,那么这个轮廓看起来应该是像下图这样的: J(θ) 是一个关于参数 θ0 θ1 和 θ2 的函数(此处忽略 θ0 所以暂时不考虑θ0)。并假想一个函数的变量只有 θ1 和 θ2。 但如果x1的取值范围远远大于x2的取值范围的话,那么最终画出来的代价函数J(θ)的轮廓图就会呈现出这样一种非常偏斜,并且椭圆的形状 2000 和 5的比例 会让这个椭圆更加瘦长。所以,这是一个又瘦又高的 椭圆形轮廓图 就是这些非常高大细长的椭圆形构成了代价函数 J(θ) 。 而如果你用这个代价函数来运行梯度下降的话,你要得到梯度值,最终可能需要花很长一段时间并且可能会来回波动,然后会经过很长时间,最终才收敛到全局最小值。 可以想像,如果这些轮廓再被放大一些的话,如果你画的再夸张一些,把它画的更细更长,那么可能情况会更糟糕 。梯度下降的过程可能更加缓慢,需要花更长的时间,反复来回振荡,最终才找到一条正确通往全局最小值的路。 在这样的情况下一种有效的方法是进行特征缩放(feature scaling) 。 具体来说,把特征x定义为房子的面积大小,除以2000; 并且把x2定义为卧室的数量除以5。那么这样的话 表示代价函数 J(θ) 的轮廓图的形状就会变得偏移没那么严重,可能看起来更圆一些了。如果你用这样的代价函数来执行梯度下降的话,可以从数学上来证明,梯度下降算法就会找到一条更捷径的路径通向全局最小,而不是像刚才那样沿着一条让人摸不着头脑的路径,一条复杂得多的轨迹,来找到全局最小值。 因此,通过特征缩放,通过”消耗掉”这些值的范围,在这个例子中,我们最终得到的两个特征 x1 和 x2 都在0和1之间,这样你得到的梯度下降算法就会更快地收敛。 3.2 特征范围 我们执行特征缩放时,通常的目的是将特征的取值约束到-1到+1的范围内: 你的特征x0是总是等于1,因此这已经是在这个范围内。但对其他的特征 你可能需要通过除以不同的数 来让它们处于同一范围内。-1 和 +1这两个数字并不是太重要,所以 如果你有一个特征x1 它的取值在0和3之间,是没问题的。如果你有另外一个特征取值在-2 到 +0.5之间这也没什么关系,这也非常接近 -1 到 +1的范围,这些都可以。 但如果你有另一个特征,比如叫 x3 假如它的范围在 -100到+100之间,那么这个范围跟-1到+1就有很大不同了。所以这可能是一个不那么好的特征。类似地,如果你的特征在一个非常非常小的范围内,比如另外一个特征 x4 它的范围在 0.0001和+0.0001之间,那么这同样是一个 比-1到+1小得多的范围。因此同样会认为这个特征也不太好。 所以,可能你认可的范围也许可以大于或者小于-1到+1,但是也别太大,只要大得不多就可以接受。比如 +100 或者也别太小,比如这里的0.001。不同的人有不同的经验。但是我一般是这么考虑的,如果一个特征是在 -3 到 +3 的范围内,那么你应该认为这个范围是可以接受的。 但如果这个范围大于了-3到+3的范围,我可能就要开始注意了。如果它的取值 在-1/3 到+1/3的话,我觉得 还不错,可以接受。或者是0到1/3或-1/3到0,这些典型的范围,我都认为是可以接受的。但如果特征的范围 取得很小的话,比如像这里的0.0001你就要开始考虑进行特征缩放了。 因此,总的来说不用过于担心你的特征是否在完全 相同的范围或区间内,但是只要他们都只要它们足够接近的话,梯度下降法就会正常地工作。 3.3 Mean Normalization(均值归一化)除了在特征缩放中将特征除以最大值以外,有时候我们也会进行一个称为均值归一化的工作(mean normalization) 。 如果你有一个特征 xi 你就用xi-μi来替换,通过这样做 让你的特征值具有为0的平均值。我们不需要把这一步应用到x0中,因为x0总是等于1的,所以它不可能有为0的的平均值。但是对其他的特征来说,比如房子的大小,取值介于0到2000,并且假设房子面积的平均值是等于1000的。那么你可以用这个公式将x1的值变为,x1减去平均值μ1再除以2000。类似地,如果你的房子有五间卧室 ,并且平均一套房子有两间卧室,那么可以使用这个公式来归一化你的第二个特征x2。 在这两种情况下,你可以算出新的特征x1和x2这样它们的范围可以在-0.5和+0.5之间,当然这肯定不对。x2的值实际上肯定会大于0.5,但很接近。更一般的规律是 你可以用这样的公式:(x1 - μ1)/S1来替换原来的特征x1。其中定义μ1的意思是: 在训练集中: x1:平均值 S1:特征值的范围(最大值减去最小值 最大值减去最小值,或者学过标准差的同学可以记住 也可以把S1设为变量的标准差,但其实用最大值减最小值就可以了) 类似地,对于第二个 特征 x2 你也可以用同样的这个特征减去平均值,再除以范围来替换原特征。范围的意思依然是最大值减最小值。这类公式将你的特征 变成这样的范围,也许不是完全这样,但大概是这样的范围。 有些同学可能比较仔细,如果我们用最大值减最小值来表示范围的话。这里的5有可能应该是4 如果最大值为5,那么减去最小值1,这个范围值就是4 。但不管咋说,这些取值都是非常近似的,只要将特征转换为相近似的范围就都是可以的。 特征缩放其实并不需要太精确,只是为了让梯度下降 能够运行得更快一点而已。 4. Learning Rate(学习效率)这一章节我们来介绍如何选择学习率α 以及怎样确定 梯度下降正常工作。 Debugging gradient descent(调试渐变下降):用X轴上的迭代次数绘制一个图。现在小区的成本函数,J(θ)在梯度下降迭代次数。如果J(θ)不断增加,那么你可能需要减少α。 Automatic convergence test(自动收敛测试) :如果该声明收敛(θ)小于E在一次迭代中减少,其中E是一些小的值,如10−3。然而,在实际应用中很难选择这个阈值。 如果学习率α足够小,那么J(θ)会在每个迭代中减少。 总结: 如果α太小:收敛速度慢。 如果α太大:可能不会在每次迭代中减少,因此可能不会收敛。 本文资料部分来源于吴恩达 (Andrew Ng) 博士的斯坦福大学机器学习公开课视频教程。 [1] 网易云课堂机器学习课程:http://open.163.com/special/opencourse/machinelearning.html[2] coursera课程:https://www.coursera.org/learn/machine-learning/]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
<tag>线性回归</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习实战]K-近邻算法]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98%5DK-%E8%BF%91%E9%82%BB%E7%AE%97%E6%B3%95%2F</url>
<content type="text"><![CDATA[1. K-近邻算法概述(k-Nearest Neighbor,KNN)K-近邻算法采用测量不同的特征值之间的距离方法进行分类。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。 优点:精度高、对异常数据不敏感、无数据输入假定。 缺点:计算复杂度高、空间复杂度高。 适用数据范围:数值型和标称型。 KNN工作原理是:存在一个样本数据集合(训练样本集),并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似的数据(最近邻)的分类标签。 一般来说我们只选择样本数据集中前k个最相似的数据。通常k是不大于20的整数。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。 12345678KNN的一般流程:1.收集数据:可使用任何方法。2.准备数据:距离计算所需要的数值,最好是结构化的数据格式。3.分析数据:可使用任何方法。4.训练算法:此步骤不适用与K-近邻算法5.测试算法:计算错误率。6.使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。 2. 准备数据集在构造完整的k-近邻算法之前,我们还需要编写一些基本的通用函数,新建KNN.py文件,新增以下代码: 1234567891011121314151617181920212223242526#!/usr/bin/python# -*- coding: UTF-8 -*-from numpy import *"""函数说明:创建数据集Parameters: 无Returns: group - 数据集 labels - 分类标签"""def createDataSet(): #四组二维特征 group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) #四组特征的标签 labels = ['A','B','C','D'] return group, labelsif __name__ == '__main__': #创建数据集 group, labels = createDataSet() #打印数据集 print(group) print(labels) 3. k-近邻算法实现对未知类别属性的数据集中的每个点一次执行以下操作: 计算已知类别数据集中的点与当前点之间的距离; 按照距离增序排序; 选取与当前点距离最近的k个点; 决定这k个点所属类别的出现频率; 返回前k个点出现频率最高的类别作为当前点的预测分类。 1234567891011121314151617181920212223242526272829303132333435363738394041424344# -*- coding: UTF-8 -*-from numpy import *import operator"""函数说明:kNN算法,分类器Parameters: inX - 用于分类的数据(测试集) dataSet - 用于训练的数据(训练集) labes - 分类标签 k - kNN算法参数,选择距离最小的k个点Returns: sortedClassCount[0][0] - 分类结果"""def classify0(inX, dataSet, labels, k): #numpy函数shape[0]返回dataSet的行数 dataSetSize = dataSet.shape[0] #在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet #二维特征相减后平方 sqDiffMat = diffMat**2 #sum()所有元素相加,sum(0)列相加,sum(1)行相加 sqDistances = sqDiffMat.sum(axis=1) #开方,计算出距离 distances = sqDistances**0.5 #返回distances中元素从小到大排序后的索引值 sortedDistIndices = distances.argsort() #定一个记录类别次数的字典 classCount = {} for i in range(k): #取出前k个元素的类别 voteIlabel = labels[sortedDistIndices[i]] #dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。 #计算类别次数 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #python3中用items()替换python2中的iteritems() #key=operator.itemgetter(1)根据字典的值进行排序 #key=operator.itemgetter(0)根据字典的键进行排序 #reverse降序排序字典 sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #返回次数最多的类别,即所要分类的类别 return sortedClassCount[0][0] 计算距离时直接使用了欧式距离公式,计算两个向量点之间的距离: 计算完所有点之间的距离后,可以对数据按照从小到大的次序排序。然后,确定前k个距离最小元素所在的主要分类,输入k总是正整数;最后,将classCount字典分解为元组列表,然后按照第二个元素的次序对元组进行排序,最后返回发生频率最高的元素标签。 预测数据所在分类: 1>>> kNN.classify([0, 0], group, labels, 3) 输出结果应该是B。 4. 测试分类器为了测试分类器的效果,我们可以使用已知答案的数据,当然答案不能告诉分类器,检验分类器给出的结果是否符合预期结果。通过大量的测试数据,我们可以得到分类器的错误率——分类器给出错误结果的次数除以测试执行的总数。错误率是常用的评估方法,主要用于评估分类器在某个数据集上的执行效果。完美分类器的错误率为0,最差分类器的错误率是1.0,在这种情况下,分类器根本就无法找到一个正确答案。然而错误率几乎不会达到1.0,因为即使是随机猜测,也会有一定概率猜对的。因此,错误率一般存在一个上限,且具体的值会与各类型之间的比例关系直接相关。 [1]KNN维基百科:https://zh.wikipedia.org/wiki/%E6%9C%80%E8%BF%91%E9%84%B0%E5%B1%85%E6%B3%95 我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=b5vh0mme3g9n]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
<tag>K-近邻</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习Lesson 3]梯度下降算法]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0Lesson%203%5D%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E7%AE%97%E6%B3%95%2F</url>
<content type="text"><![CDATA[1. Gradient Descent(梯度下降)梯度下降算法是很常用的算法,可以将代价函数J最小化。它不仅被用在线性回归上,也被广泛应用于机器学习领域中的众多领域。 1.1 线性回归问题应用我们有一个函数J(θ0,θ1),要使其最小化minJ(θ0,θ01): Outline 对θ0,θ1开始进行一些猜测通常将初θ0,θ1初始化为0 在梯度算法中,要做的就是不停的一点点改变θ0和θ1试图通过这种改变使得J(θ0,θ1)变小,直到找到J的最小值或者局部最小值。 1.2 梯度算法工作原理 现在我们把这个图像想象为一座山,想像类似这样的景色 :公园中有两座山,想象一下你正站立在山的这一点上 站立在你想象的公园这座红色山上。在梯度下降算法中,我们要做的就是旋转360度,看看我们的周围,并问自己,我要在某个方向上,用小碎步尽快下山。如果我想要下山。如果我想尽快走下山,这些小碎步需要朝什么方向? 如果我们站在山坡上的这一点,你看一下周围,你会发现最佳的下山方向,大约是那个方向。 现在你在山上的新起点上 你再看看周围 然后再一次想想 我应该从什么方向迈着小碎步下山? 然后你按照自己的判断又迈出一步 往那个方向走了一步 然后重复上面的步骤。从这个新的点,你环顾四周并决定从什么方向将会最快下山。然后又迈进了一小步,并依此类推,直到你接近这里,直到局部最低点的位置。 现在想象一下,我们在刚才的右边一些的位置,对梯度下降进行初始化。想象我们在右边高一些的这个点。开始使用梯度下降。如果你重复上述步骤,停留在该点,并环顾四周,往下降最快的方向迈出一小步,然后环顾四周又迈出一步,然后如此往复。如果你从右边不远处开始梯度下降算法将会带你来到这个右边的第二个局部最优处。 如果从刚才的第一个点出发,你会得到这个局部最优解 但如果你的起始点偏移了一些,起始点的位置略有不同 你会得到一个非常不同的局部最优解。这就是梯度下降算法的一个特点。 1.3 梯度下降算法定义。 :=:赋值符号(Assignment). α:这里的α是一个数字,被称为学习速率(learning rate)。在梯度下降算法中,它控制了我们下山时会迈出多大的步子。 微分项。 在梯度下降中,我们要更新θ0和θ1。当 j=0 和 j=1 时 会产生更新。所以你将更新J、θ0还有θ1。实现梯度下降算法的微妙之处是,在这个表达式中,如果你要更新这个等式,你需要同时更新 θ0和θ1。 θ0和θ1需要同步更新,右侧是非同步更新,错误。 1.4 梯度下降和代价函数 梯度下降是很常用的算法,它不仅被用在线性回归上 和线性回归模型还有平方误差代价函数。 当具体应用到线性回归的情况下,可以推导出一种新形式的梯度下降法方程: m:训练集的大小 θ0与θ1同步改变 xi和yi:给定的训练集的值(数据)。 我们已经分离出两例θj:θ0和θ1为独立的方程;在θ1中,在推导最后乘以Xi。以下是推导∂/∂θjJ(θ)的一个例子: 这一切的关键是,如果我们从猜测我们的假设开始,然后反复应用这些梯度下降方程,我们的假设将变得越来越精确。 因此,这只是原始成本函数J的梯度下降。这个方法是在每个步骤的每个训练集中的每一个例子,被称为批量梯度下降。注意,虽然梯度下降一般容易受到局部极小值的影响,但我们在线性回归中所提出的优化问题只有一个全局,没有其他局部最优解,因此梯度下降总是收敛(假定学习率α不是太大)到全局最小值。实际上,j是凸二次函数。这里是一个梯度下降的例子,它是为了最小化二次函数而运行的。 上面所示的椭圆是二次函数的轮廓图。也表明是通过梯度下降的轨迹,它被初始化为(48,30)。X在图(连接的直线)的标志,θ梯度穿过它收敛到最小的连续值。 本文资料部分来源于吴恩达 (Andrew Ng) 博士的斯坦福大学机器学习公开课视频教程。 [1]网易云课堂机器学习课程:http://open.163.com/special/opencourse/machinelearning.html[2]coursera课程:https://www.coursera.org/learn/machine-learning/]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
<tag>梯度下降</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习Lesson 2]代价函数之线性回归算法]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0Lesson%202%5D%E4%BB%A3%E4%BB%B7%E5%87%BD%E6%95%B0%E4%B9%8B%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92%E7%AE%97%E6%B3%95%2F</url>
<content type="text"><![CDATA[本章内容主要是介绍:单变量线性回归算法(Linear regression with one variable) 1. 线性回归算法(linear regression)1.1 预测房屋价格下图是俄勒冈州波特兰市的住房价格和面积大小的关系: 该问题属于监督学习中的回归问题,让我们来复习一下: 监督学习(Supervised’Learning’):对示例数据给出“正确答案”。 回归问题(Regression ‘Problem’):根据之前的数据预测出一个准确的输出值 。 1.2 训练集 m=训练样本数量 x’s=输入变量/特征量 y’s=输出变量/目标变量,预测结果 (x,y)表示一个训练样本。 x(1) 指的是 第一个训练集里值为2104的输入值, 这个就是第一行里的x x(2) 等于1416。这是第二个x y(1) 等于460,这是第一个训练集样本的y值, 这就是(1)所代表的含义。 这就是一个监督学习算法的工作方式,我们可以看到这里有我们的训练集里房屋价格,我们把它喂给我们的学习算法,然后输出一个函数。 按照惯例,通常表示为小写h代表hypothesis(假设) h表示一个函数。输入是房屋尺寸大小,就像你朋友想出售的房屋。因此,h 根据输入的 x 值来得出 y 值。 y值对应房子的价格。所以h是一个从x到y的函数映射 。 y关于x的线性函数 : 1hθ(x)=θ0+θ1*x 这个模型被称为线性回归(linear regression)模型。 这实际上是关于单个变量的线性回归,这个变量就是x 根据x来预测所有的价格函数。同时, 对于这种模型有另外一个名称,称作单变量线性回归 单变量是对一个变量的一种特别的表述方式。总而言之 这就是线性回归。 2. 代价函数(Cost Function)任何能够衡量模型预测出来的值h(θ)与真实值y之间的差异的函数都可以叫做代价函数C(θ),如果有多个样本,则可以将所有代价函数的取值求均值,记做J(θ)。 J(θ0,θ1)=12m$\sum$i=1m(y^i−yi)2=12m∑i=1m(hθ(xi)−yi)2 m:训练样本的个数; hθ(x):用参数θ和x预测出来的y值; y:原训练样本中的y值,也就是标准答案 上角标(i):第i个样本 3. 代价函数1(简化版):当θ0=0时hθ(x)=θ1x,如下图: 重要公式 Hypothesis: 假设。这个例子中是尺寸对于房价关系的预测。 Parameters: 参数。 Cost Function:代价函数。 Goal: 优化目标。代价最小化。 3.1 斜率为1时的代价函数 (1)假设函数 x轴为面积,y轴为房价 假设函数 h(x) 对于一个固定的θ1,这是一个关于x 的函数。 所以这个假设函数就是一个关于 x 这个房子大小的函数。 (2)代价函数 x轴为假设函数的斜率,y即代价大小 代价函数 J 是一个关于参数 θ1 的函数,而 θ1 控制着这条直线的斜率 。 3.2 斜率为0.5时的代价函数 斜率为0.5时,取3个样本(m=3):(0.5,1),(1,2),(1.5,3)。套公式得出J(0.5)=0.58同理,J(0)=1/6(1²+2²+3²)=14/6,求出更多的点之后,我们得出类似以下函数: 学习算法的优化目标是我们想找到一个 θ1 的值,来将 J(θ1) 最小化。这是我们线性回归的目标函数。 上面的曲线中,让 J(θ1) 最小化的值是 θ1=1。这个确实就对应着最佳的通过了数据点的拟合直线 。这条直线就是由 θ1=1 的设定而得到的。 对于这个特定的训练样本,我们最后能够完美地拟合 这就是为什么最小化 J(θ1),对应着寻找一个最佳拟合直线的目标。 4. 代价函数2:完整版包含θ0、θ1两个参数的代价函数呈现出来的是类似下图的三维曲面图,两个轴分别表示θ0、θ1。 在ML中,一般使用轮廓图( contour plot 或 contour figure 的意思)描述该模型。 4.1 轮廓图简介 右侧图形就是一个轮廓图,两个轴分别表示θ0和θ1。 而这些一圈一圈的椭圆形,每一个圈就表示J(θ0,θ1) 相同的所有点的集合。 如图选取三个点,这三个点都表示相同的 J(θ0,θ1) 的值。横纵坐标分别是θ0, θ1 这三个点的 J(θ0,θ1) 值是相同的。我们需要算的代价函数即为圆心的点,此时我们的代价最小。 4.2 第一组数据 我们选取一组数据,θ0=800,θ1=-0.15,此时我们可以对应得到一个左边这样一条线。 以这组 θ0,θ1 为参数的这个假设 h(x) 并不是数据的较好拟合。并且你也发现了这个代价值 距离最小值点还很远。也就是说这个代价值还是算比较大的,因此不能很好拟合数据。 4.3 第二组数据 θ0=360,θ1=0。我们可以得到h(x)=360+0*x这样一条直线。同样不能很好的拟合数据。 4.4 第三组数据最后一个例子: 这个点其实不是最小值,但已经非常靠近最小值点了。 这个点对数据的拟合就很不错,它对应这样两个θ0 和 θ1 的值。同时也对应这样一个 h(x) 这个点虽然不在最小值点,但非常接近了。 因此误差平方和,或者说 训练样本和假设的距离的平方和,这个距离值的平方和 非常接近于最小值,尽管它还不是最小值。 5. 小结通过这些图形,本篇文章主要是帮助理解这些代价函数 J 所表达的值;它们是什么样的它们对应的假设是什么样的;以及什么样的假设对应的点更接近于代价函数J的最小值。 我们真正需要的是一种有效的算法,能够自动地找出这些使代价函数J取最小值的参数θ0和θ1来。我们也不希望编个程序 把这些点画出来,然后人工的方法来读出这些点的数值,这很明显不是一个好办法。 事实上在深入机器学习的过程中, 我们会遇到更复杂、更高维度、更多参数的情况。而这些情况是很难画出图的,因此更无法将其可视化,因此我们真正需要的,是编写程序来找出这些最小化代价函数的θ0和θ1的值。在后续文章中将介绍一种算法 能够自动地找出能使代价函数 J最小化的参数θ0和θ1的值。 本文资料部分来源于吴恩达 (Andrew Ng) 博士的斯坦福大学机器学习公开课视频教程。 [1]网易云课堂机器学习课程:http://open.163.com/special/opencourse/machinelearning.html[2]coursera课程:https://www.coursera.org/learn/machine-learning/]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
<tag>线性回归</tag>
</tags>
</entry>
<entry>
<title><![CDATA[[机器学习Lesson 1] 机器学习简介]]></title>
<url>%2F%5B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0Lesson%201%5D%20%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E7%AE%80%E4%BB%8B%2F</url>
<content type="text"><![CDATA[1. Machine Learning definition(机器学习定义) Arthur Samuel(1959年)将机器学习非正式定义为:在不直接针对问题进行编程的情况下,赋予计算机学习能力的一个研究领域。创造西洋棋程序,可以和自己对战。 Tom Mitchell(1998年)提出一个更为正式关于机器学习的定义 :对于一个计算机程序来说:给它一个任务T和一个性能测量方法P,如果在经验E的影响下,P对T的测量结果得到了改进,那么就说改程序从E中学习。 E = the experience of playing many games of checkers T = the task of playing checkers. P = the probability that the program will win the next game. 2. Supervised Learning (监督学习) 它被称作监督学习是因为对于每个数据来说 我们给出了 “正确的答案”。你有一些问题和他们的答案,你要做的有监督学习就是学习这些已经知道答案的问题。然后你就具备了经验了,这就是学习的成果。然后在你接受到一个新的不知道答案的问题的时候,你可以根据学习得到的经验,得出这个新问题的答案。(试想一下高考不正是这样,好的学习器就能有更强的做题能力,考好的分数,上好的大学…..)。我们有一个样本数据集,如果对于每一个单一的数据根据它的特征向量我们要去判断它的标签(算法的输出值),那么就是有监督学习。通俗的说,有监督学习就是比无监督学习多了一个可以表达这个数据特质的标签。 包含回归(Regression)和分类(Classfication)。 举例: 房价 与 面积的关系 2.1 Classfication (分类任务)离散变量预测,设定了标准答案,复合条件,是或否。 举例: 肿瘤良性/恶性 与 肿瘤大小的关系。(0或1结构) 年纪 与 肿瘤大小关系。(聚合结构) 预测明天的气温是多少度 Support Vector machines(支持向量机的算法):可以吧数据映射到无限维空间中。 问题: 如何把一个无限维的向量映射到计算机内存中? 如何表示一个无限纬空间中的点? 2.2 Regression(回归任务)连续变量预测。 举例: 预测明天的气温是多少度。 3. Unsupervised Learning(无监督学习) 数据聚合、分类。 我们有一些问题,但是不知道答案,我们要做的无监督学习就是按照他们的性质把他们自动地分成很多组,每组的问题是具有类似性质的(比如数学问题会聚集在一组,英语问题会聚集在一组,物理……..)。 所有数据只有特征向量没有标签,但是可以发现这些数据呈现出聚群的结构,本质是一个相似的类型的会聚集在一起。把这些没有标签的数据分成一个一个组合,就是聚类(Clustering)。比如Google新闻,每天会搜集大量的新闻,然后把它们全部聚类,就会自动分成几十个不同的组(比如娱乐,科技,政治……),每个组内新闻都具有相似的内容结构。 举例: 提供一组数据,不提供任何数据的正确答案,你能否在这组数据中寻找到一些有趣的数据结构? 基因数据分组。 聚合算法处理图像,对像素数据进行聚合分组,得到类似素描的效果,等效表达。 图像处理,将图像分成不同区域,像素分到不同区域。创建3D模型,创造类似AR的效果。 计算机集群,社交网络分析,市场划分,航天数据分析。 3.1 Cocktail party problem(鸡尾酒会问题)假设我们在参加一个鸡尾酒会,有很多人参加,在环境嘈杂,很多人说话的情况下,能否把感兴趣的某个人的声音单独从嘈杂的背景音中提取出来?规律:不同麦克风收集到说话者声音大小不一样。 算法A将人声从人声中分离 独立组件分析将人声从音乐中分离 其他应用: 文本处理 理解功能分级 使用MATLAB一行代码实现以上算法。 3.2 ICA algorithm1[W,s,v] = svd((repmat(sum(x.*x,1),size(x,1),1).*x)*x'); 4. Reinforcement Learning(强化算法学习) 基本概念是一个被称为 回报函数的概念。使用在不需要进行一次决策的情形中。 举例 使用监督学习进行癌症预测,预测一个病人肿瘤是否为恶性。你的预测决定了病人是生死。通过决策产生一个结论,要么对,要么错。 在强化学习问题中,通常会一段时间内做出一系列的决策 举例 自动直升机:给你自动直升机的钥匙,能否写个程序让它飞起来?如果做了一个坏的决策,飞机可能不会马上摔下来,只有你连续做出很多坏的决策时,飞机才会摔下来。相反的,只要连续的做出正确的决策,飞机就可以飞起来了。 训狗,正确奖励;错误惩罚。 机器人领域。]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>机器学习</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git Workflow简介]]></title>
<url>%2FGit%20Workflow%E7%AE%80%E4%BB%8B%2F</url>
<content type="text"><![CDATA[1. Git WorkFlow介绍Git Flow是构建在Git之上的一个组织软件开发活动的模型,是在Git之上构建的一项软件开发最佳实践。Git Flow是一套使用Git进行源代码管理时的一套行为规范和简化部分Git操作的工具。 2010年5月,在一篇名为“一种成功的Git分支模型”的博文中,@nvie介绍了一种在Git之上的软件开发模型。通过利用Git创建和管理分支的能力,为每个分支设定具有特定的含义名称,并将软件生命周期中的各类活动归并到不同的分支上。实现了软件开发过程不同操作的相互隔离。这种软件开发的活动模型被nwie称为“Git Flow”。 一般而言,软件开发模型有常见的瀑布模型、迭代开发模型、以及最近出现的敏捷开发模型等不同的模型。每种模型有各自应用场景。Git Flow重点解决的是由于源代码在开发过程中的各种冲突导致开发活动混乱的问题。因此,Git flow可以很好的于各种现有开发模型相结合使用。 2. Git VS SVN SVN Git 分布式管理 集中式管理 元数据存储 文件存储 offline log online log 有本地分支 无本地分支 没有全局版本号 有全局版本号 内容完整性(SHA-1) N/A github,gitlab等配套 N/A 3.分支3.1 历史分支(Master , Develop)Gitflow工作流使用2个分支来记录项目的历史。master分支存储了正式发布的历史,而develop分支作为功能的集成分支。 这样也方便master分支上的所有提交分配一个版本号。 3.2 功能分支(Feature)每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。 但功能分支不是从master分支上拉出新分支,而是使用develop分支作为父分支。当新功能完成时,合并回develop分支。 新功能提交应该从不直接与master分支交互。 3.3 发布分支(Release)一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能:本期要发布的所有功能已开发完成,测试通过。就从develop分支上fork一个release发布分支。 release分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上—— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。 一旦对外发布的工作都完成了,发布分支合并到master分支并分配一个版本号打好Tag。 另外,这些从新建发布分支以来的做的修改要合并回develop分支。 使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。 这也打造定义良好的开发阶段(比如,可以很轻松地说,『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。 3.4 维护分支(Hotfix)维护分支或说是热修复(hotfix)分支用于生成快速给产品发布版(production releases)打补丁,这是唯一可以直接从master分支fork出来的分支。 修复完成,修改应该马上合并回master分支和develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。 为Bug修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。 你可以把维护分支想成是一个直接在master分支上处理的临时发布。 4. 实际 初始化 1git flow init 开发一个功能 12git flow feature start <your feature>git flow feature finish <your feature> 完成开发一个功能 12git flow feature publish <name>git flow feature pull <remote> <name> 发布版本 12git flow release start <release>git flow release finish <release> 修补bug 12git flow hotfix start <release>git flow hotfix finish <release> 5.常用命令创建分支: git branch mybranch切换分支: git checkout mybranch创建并切换分支: git checkout -b mybranch更新master主线上的东西到该分支上:git rebase master切换到master分支:git checkout master更新mybranch分支上的东西到master上:git rebase mybranch提交:git commit -a对最近一次commit的进行修改:git commit -a –amendcommit之后,如果想撤销最近一次提交(即退回到上一次版本)并本地保留代码:git reset HEAD^合并分支:(merge from) git checkout master$ git merge mybranch (merge from mybranch)删除分支: git branch -d mybranch强制删除分支: git branch -D mybranch列出所有分支: git branch查看各个分支最后一次提交: git branch -v查看哪些分支合并入当前分支: git branch –merged查看哪些分支未合并入当前分支: git branch –no-merged更新远程库到本地: git fetch origin推送分支: git push origin mybranch取远程分支合并到本地: git merge origin/mybranch取远程分支并分化一个新分支: git checkout -b mybranch origin/mybranch 6. 学习资料推荐 Git的资料整理 Pro Git book 猴子都能懂的Git入门系列]]></content>
<categories>
<category>Git</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git常用命令速查]]></title>
<url>%2FGit%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E9%80%9F%E6%9F%A5%2F</url>
<content type="text"><![CDATA[Alias下面的只是例子,想改成什么跟随自己的意愿即可。12345git config --global alias.st status //status 缩写成 stgit config --global alias.co checkout //checkout 缩写成 cogit config --global alias.br branch //branch 缩写成 brgit config --global alias.ci commit //commit 缩写成 cigit config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" 如果不想使用了,删除掉的话,直接删除 conf 配置文件中的行即可,global 的在当前用户下vim ~/.gitconfig 删除alias下你配置的内容接口;若是当前仓库则在 .git/config 中。 Git ConfigGit 配置文件分为三级,系统级(–system)、用户级(–global)和目录级(–local),三者的使用优先级以离目录 (repository)最近为原则,如果三者的配置不一样,则生效优先级 目录级>用户级>系统级,可以通过 git config --help 查看更多内容。 系统级配置存储在 /etc/gitconfig 文件中,可以使用 git config --system user.name "jim" ,git config --sytem user.email "[email protected]" 来进行配置,该配置对系统上所有用户及他们所拥有的仓库都生效的配置值。 用户级存储在每个用户的 ~/.gitconfig 中,可以使用 git config --global user.name "jim" ,git config --global user.email "[email protected]" 来进行配置,该配置对当前用户上所有的仓库有效。 目录级存储在每个仓库下的 .git/config 中,可以使用 git config --local user.name "jim" , git config --local user.email "[email protected]" 来进行配置,只对当前仓库生效。 Basic Usage 添加文件到暂存区(staged):git add filename / git stage filename 将所有修改文件添加到暂存区(staged): git add --all / git add -A 提交修改到暂存区(staged):git commit -m 'commit message' / git commit -a -m 'commit message' 注意理解 -a 参数的意义 从Git仓库中删除文件:git rm filename 从Git仓库中删除文件,但本地文件保留:git rm --cached filename 重命名某个文件:git mv filename newfilename 或者直接修改完毕文件名 ,进行git add -A && git commit -m 'commit message' Git会自动识别是重命名了文件 获取远程最新代码到本地:git pull (origin branchname) 可以指定分支名,也可以忽略。pull 命令自动 fetch 远程代码并且 merge,如果有冲突,会显示在状态栏,需要手动处理。更推荐使用:git fetch 之后 git merge --no-ff origin branchname 拉取最新的代码到本地仓库,并手动 merge 。 Repository 检出(clone)仓库代码:git clone repository-url / git clone repository-url local-directoryname 例如,clone jquery 仓库到本地: git clone git://github.com/jquery/jquery.git clone jquery 仓库到本地,并且重命名为 my-jquery :git clone git://github.com/jquery/jquery.git my-jquery 查看远程仓库:git remote -v 添加远程仓库:git remote add [name] [repository-url] 删除远程仓库:git remote rm [name] 修改远程仓库地址:git remote set-url origin new-repository-url 拉取远程仓库: git pull [remoteName] [localBranchName] 推送远程仓库: git push [remoteName] [localBranchName] 例: git push -u orgin master 将当前分支推送到远端master分支 将本地 test 分支提交到远程 master 分支: git push origin test:master (把本地的某个分支 test 提交到远程仓库,并作为远程仓库的 master 分支) 提交本地 test 分支作为远程的 test 分支 :git push origin test:test Checkoutcheckout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。 匿名分支:如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像 master~3 类似的东西,就得到一个匿名分支,称作 detached HEAD(被分离的 HEAD 标识)。 当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)一旦此后你切换到别的分支,比如说 master,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用 2eecb。详细查看:visual-git-guide#detached但是,如果你想保存这个状态,可以用命令 git checkout -b name 来创建一个新的分支。 Log Description : Shows the commit logs.The command takes options applicable to the git rev-list command to control what is shown and how, and options applicable to the git diff-* commands to control how the changes each commit introduces are shown.git log [options] [revision range] [path] 常用命令整理如下: 查看日志:git log 查看日志,并查看每次的修改内容:git log -p 查看日志,并查看每次文件的简单修改状态:git log --stat 一行显示日志:git log --pretty=oneline / git log --pretty='format:"%h - %an, %ar : %s' 查看日志范围: 查看最近10条日志:git log -10 查看2周前:git log --until=2week 或者指定2周的明确日期,比如:git log --until=2015-08-12 查看最近2周内:git log --since=2week 或者指定2周明确日志,比如:git log --since=2015-08-12 只查看某个用户的提交:git log --committer=user.name / git log --author=user.name 只查看提交msg中包含某个信息的历史,比如包含’测试’两个字的:git log --grep '测试' 试试这个 : git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 感觉好用就加成 alias ,方便日后用,方法:git config --global alias.aliasname 'alias-content' 更多用法:Viewing the History – 《Pro Git2》 log 的目的就是为了查看改动点来排查问题,除了 git log 还可以使用 git show 、git blame 来查看文件的改动。 Who changed what and when in a file : git blame $file 查看一次 commit 中修改了哪些文件: git show --pretty="" --name-only <sha1-of-commit> 或者 git diff-tree --no-commit-id --name-only -r <sha1-of-commit> Undo things 上次提交 msg 错误/有未提交的文件应该同上一次一起提交,需要重新提交备注:git commit --amend -m 'new msg' 修改上次提交的 author、email :git commit --amend --author="newName <newEmail>" 修改整个历史记录中的某些错误的 author、email: git rebase 或者 git filter-branch 1234567891011121314151617181920212223 # git rebase 模式 git rebase -i -p 76892625a7b126f4772f8d7e331ada3552c11ce1 # 弹出编辑器,在需要修改的 commit 处 由 picked 改变为 edit ,然后 wq 退出 vim; git commit --amend --author 'newName <newEmail>' # 执行后即变更了相应的 author 和 email git rebase --continue ################################################################ # git filter-branch 模式 https://help.github.com/articles/changing-author-info/git filter-branch --env-filter 'OLD_EMAIL="[email protected]"CORRECT_NAME="Your Correct Name"CORRECT_EMAIL="[email protected]"if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]then export GIT_COMMITTER_NAME="$CORRECT_NAME" export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"fiif [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]then export GIT_AUTHOR_NAME="$CORRECT_NAME" export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"fi' --tag-name-filter cat -- --branches --tags 一次git add -A后,需要将某个文件撤回到工作区,即:某个文件不应该在本次commit中:git reset HEAD filename 撤销某些文件的修改内容:git checkout -- filename 注意:一旦执行,所有的改动都没有了,谨慎!谨慎!谨慎! 将工作区内容回退到远端的某个版本:git reset --hard <sha1-of-commit> Resetreset命令把当前分支指向另一个位置,并且有选择的变动工作目录和索引,也用来在从历史仓库中复制文件到索引,而不动工作目录。 将工作区内容回退到远端的某个版本:git reset --hard <sha1-of-commit> git reset --hard HEAD^ reset index and working directory , 以来所有的变更全部丢弃,并将 HEAD 指向 git reset --soft HEAD^ nothing changed to index and working directory ,仅仅将 HEAD 指向 ,所有变更显示在 “changed to be committed”中 git reset --mixed HEAD^ default,reset index ,nothing to working directory 默认选项,工作区代码不改动,添加变更到index区 Revert git revert will create a new commit that’s the opposite (or inverse) of the given SHA. If the old commit is “matter”, the new commit is “anti-matter”—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit.This is Git’s safest, most basic “undo” scenario, because it doesn’t alter history—so you can now git push the new “inverse” commit to undo your mistaken commit. 1234git revert [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<keyid>]] <commit>…git revert --continuegit revert --quitgit revert --abort Revert VS ResetDiff 查看工作区(working directory)和暂存区(staged)之间差异:git diff 查看工作区(working directory)与当前仓库版本(repository)HEAD版本差异:git diff HEAD 查看暂存区(staged)与当前仓库版本(repository)差异:git diff --cached / git diff --staged 不查看具体改动,只查看改动了哪些类:git diff --stat Merge 解决冲突后/获取远程最新代码后合并代码:git merge branchname ,将 branchname 分支上面的代码合并到当前分支 保留该存在版本合并log:git merge --no-ff branchname 参数 --no-ff 防止 fast-forward 的提交,详情参考:the difference,fast-forward:分支内容一致,指针直接移动,并未能看出分支信息RebaseRebase 同 Merge 的结果是一样的,就是合并本地、远程的改动,但过程中还有区别。12git checkout myworkgit rebase origin 这些命令会把你的”mywork”分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁 放到”.git/rebase”目录中),然后把”mywork”分支更新 到最新的”origin”分支,最后把保存的这些补丁应用 到”mywork”分支上。一张图分清 rebase 和 merge 的区别 在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用 git-add 命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行: git rebase --continue 这样git会继续应用(apply)余下的补丁。在任何时候,你可以用 –abort 参数来终止rebase的行动,并且”mywork” 分支会回到rebase开始前的状态。 git rebase --abort Cherry Pickcherry-pick 命令”复制”一个提交节点并在当前分支做一次完全一样的新提交。 Branch workflowAone2 Git 分支开发部署模型详细解读 http://docs.alibaba-inc.com:8090/pages/viewpage.action?pageId=194872297 分支情况 origin master develop release 20161129163217010_r_release_yingyongming 20161029163217010_r_release_yingyongming feature 20161129_163448_newfeature_1 20161129_163448_newfeature_2 hotfix 20161129_163448_hotfix_1 tags 20161129163217010_r_release_newfeature_yingyongming创建分支的时候直接操作: git checkout -b feature/20161129_163448_newfeature_1 master:master永远是线上代码,最稳定的分支,存放的是随时可供在生产环境中部署的代码,当开发活动告一段落,产生了一份新的可供部署的代码时,发布成功之后,代码才会由 aone2 提交到 master,master 分支上的代码会被更新。应用上 aone2 后禁掉所有人的 master的写权限 develop:保存当前最新开发成果的分支。通常这个分支上的代码也是可进行每日夜间发布的代码,只对开发负责人开放develop权限。 feature: 功能特性分支,每个功能特性一个 feature/ 分支,开发完成自测通过后合并入 develop 分支。可以从 master 或者develop 中拉出来。 hotfix: 紧急bug分支修复分支。修复上线后,可以直接合并入master。 Git-Develop 分支模式是基于 Git 代码库设计的一种需要严格控制发布质量和发布节奏的开发模式。develop 作为固定的持续集成和发布分支,并且分支上的代码必须经过 CodeReview 后才可以提交到 Develop 分支。它的基本流程如下: 每一个需求/变更都单独从Master上创建一条Branch分支; 用户在这个Branch分支上进行Codeing活动; 代码达到发布准入条件后aone上提交Codereview,Codereview通过后代码自动合并到Develop分支; 待所有计划发布的变更分支代码都合并到Develop后,系统再 rebase master 代码到Develop 分支,然后自行构建,打包,部署等动作。 应用发布成功后Aone会基于Develop分支的发布版本打一个“当前线上版本Tag”基线; 应用发布成功后Aone会自动把Develop分支的发布版本合并回master; Branch 命令 查看分支:git branch 、git branch -v、git branch -vv (查看当前分支 tracking 哪个远端分支)、git branch --merged、git branch --no-merged 创建分支:git branch branchname 例: 基于 master 分支新建 dev 分支 : git branch dev 基于之前的某个 Commit 新开分支: git branch branchname <sha1-of-commit> 例: 基于上线的的提交 a207a38d634cc10441636bc4359cd8a18c502dea 创建 hotfix 分支 : git branch hotfix a207a38 例: 基于 remoteBranch、localBranch、commitId、tag 创建分支均可以 git checkout -b newbranch localBranch/remoteBranch/commitId/tag 例: 创建一个空的分支 123456git checkout --orphan gh-pages # 创建一个orphan的分支,这个分支是独立的 Switched to a new branch \'gh-pages\' git rm -rf . # 删除原来代码树下的所有文件 rm \'.gitignore\' #注意这个时候你用git branch命令是看不见当前分支的名字的,除非你进行了第一次commit。添加新的文件,并且 commit 掉,就能看到分支了。` 切换分支: git checkout branchname 例: 由分支 master 切换到 dev 分支:git checkout dev 创建新分支并切换到下面:git checkout -b branchname 或者 git branch branchname && git checkout branchname 例:基于 master 分支新建 dev 分支,并切换到 dev 分支上: git checkout -b dev 或 git branch dev && git checkout dev 查看分支代码不同:git diff branchname 比较 branchname 分支与当前分支的差异点,若只看文件差异,不看差异内容:git diff branchName --stat 合并分支:git merge branchname 将 branchname 分支代码合并到当前分支 删除分支:git branch -d branchname 强制删除未合并过的分支:git branch -D branchname 重命名分支: git branch -m dev development 将分支 dev 重命名为 development 查看远程分支:git branch -r 或 git branch -r -v 获取远程分支到本地:git checkout -b local-branchname origin/remote-branchname 推送本地分支到远程:git push origin remote-branchname 或 git push origin local-branchname:remote-branchname 将本地 dev 代码推送到远程 dev 分支: git push (-u) origin dev 或 git push origin dev:dev (技巧)将本地 dev 分支代码推送到远程 master 分支: git push origin dev:master 删除远程分支:git push origin :remote-branchname 或 git push origin --delete remote-branchname 手动跟踪分支,master分支追踪origin/next分支: git branch --track master origin/next 或者 git branch --set-upstream-to=origin/master 看 git 的版本是否支持。 TrackingBranch,可以通过 git branch -vv 来查看当前 track 的分支情况。新建立分支时会自动 track 相应远程分支,git checkout -b sf origin/serverfix (Branch sf set up to track remote branch serverfix from origin. Switched to a new branch ‘sf’). 也可以手动 track: git branch -u origin/serverfix (Branch serverfix set up to track remote branch serverfix from origin). 等同于命令 git checkout --track origin/serverfix “Checking out a local branch from a remote branch automatically creates what is called a “tracking branch” (or sometimes an “upstream branch”). Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git pull, Git automatically knows which server to fetch from and branch to merge into.When you clone a repository, it generally automatically creates a master branch that tracks origin/master. However, you can set up other tracking branches if you wish – ones that track branches on other remotes, or don’t track the master branch. The simple case is the example you just saw, running git checkout -b [branch] [remotename]/[branch]. This is a common enough operation that git provides the –track shorthand:” Tag 查看 tag:git tag 查找指定 tag,比如查找 V1.0. :`git tag -l ‘V1.0.‘` 会列出匹配到的,比如 V1.0.1,V1.0.1.1,V1.0.2 等 创建轻量级 tag(lightweight tags):git tag tag-name ,例如: git tag v1.0 创建 tag(annotated tags):git tag -a tag-name -m 'msg' ,例如:git tag -a v1.0.0 -m '1.0.0版本上线完毕打tag' annotated tags VS lightweight tags 可以通过命令真实查看下:git show v1.0 / git show v1.0.0 “A lightweight tag is very much like a branch that doesn’t change – it’s just a pointer to a specific commit.Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, e-mail, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). ” 查看指定 tag 信息:git show tag-name 基于历史某次提交(commit)创建 tag :git tag -a tagname <sha1-of-commit> 例:基于上线时的提交 a207a38d634cc10441636bc4359cd8a18c502dea 创建tag:git tag -a v1.0.0 a207a38 删除 tag :git tag -d tagname 拉取远程 tag 到本地:git pull remotename --tags 例如:git pull origin --tags 推送 tag 到远程服务器:git push remotename tagname 例如:git push origin v1.0.0 将本地所有 tag 推送到远程:git push remotename --tags 例如:git push origin --tags 删除远程 tag :git push origin :tagname 或者 git push origin --delete tagname 或者 git push origin :refs/tags/v0.9 Submodule添加子模块:$ git submodule add [url] [path] 如:$ git submodule add git://github.com/soberh/ui-libs.git src/main/webapp/ui-libs初始化子模块:$ git submodule init —-只在首次检出仓库时运行一次就行更新子模块:$ git submodule update —-每次更新或切换分支后都需要运行一下删除子模块:(分4步走哦) 1) $ git rm –cached [path] 2) 编辑“.gitmodules”文件,将子模块的相关配置节点删除掉 3) 编辑“ .git/config”文件,将子模块的相关配置节点删除掉 4) 手动删除子模块残留的目录 Stash经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是 git stash 命令。stash 可以获取你工作目录的中间状态,也就是你修改过的被追踪的文件和暂存的变更,并将它保存到一个未完结变更的堆栈中,随时可以重新应用。 12345678usage: git stash list [<options>] 查看当前 stash 的列表 or: git stash show [<stash>] 查看某一个版本的详细内容 or: git stash drop [-q|--quiet] [<stash>] 删除 stash 中内容 or: git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>] 将 stash 中的代码应用到工作区中 or: git stash branch <branchname> [<stash>] or: git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] [-u|--include-untracked] [-a|--all] [<message>]] or: git stash clear 清空 stash 中所有内容 oh-my-zsh 常用命令1234567891011alias g='git'alias ga='git add'alias gco='git checkout'alias gcb='git checkout -b'alias gcm='git checkout master'alias gcd='git checkout develop'alias gd='git diff'alias gf='git fetch'alias gfo='git fetch origin'alias gl='git pull'alias gp='git push']]></content>
<categories>
<category>Git</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git快速入门]]></title>
<url>%2FGit%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8%2F</url>
<content type="text"><![CDATA[Git 快速入门0. Git简介git是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。Git可以在任何时间点,把文档的状态作为更新记录保存起来。因此可以把编辑过的文档复原到以前的状态,也可以显示编辑前后的内容差异。而且,编辑旧文件后,试图覆盖较新的文件的时候(即上传文件到服务器时),系统会发出警告,因此可以避免在无意中覆盖了他人的编辑内容。 更多内容请查看Git维基百科。 1. Git Vs SVN分布式 vs 集中管理 (多份版本库 vs 一份版本库,设想下版本服务器挂了?)无需网络,随时随地进行版本控制,在没有网络的情况下你想回退到某个版本svn基本没戏;分支的新建、合并非常方便、快速,没有任何成本,基本不耗时,svn的版本基本上等同于又复制了一份代码。 stackoverflow 上关于svn和git的区别的讨论,说的很详细,请参考 Why is Git better than Subversion? Github上通过版本库结构、历史、子项目(submudle)的不同来对比两者,请参考Github的 What are the differences between SVN and Git? 2.安装通过官网安装。 下面推荐各个OS的GUI( 图形用户界面)Git工具,但还是强烈推荐使用命令行操作Git。 Windows乌龟Tortoisegithttps://tortoisegit.org/ Mac免费的SourceTree客户端。http://www.sourcetreeapp.com/ Linux不推荐客户端,可以使用发行版包含的基础软件包管理工具来安装。 如果以 Fedora 上为例,你可以使用 yum: 1$ sudo yum install git 如果你在基于 Debian 的发行版上,请尝试用 apt-get:1$ sudo apt-get install git 3. 配置Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置: /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 --system 选项的 git config 时,它会从此文件读写配置变量。 ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 可以传递 --global 选项让 Git 读写此文件。 当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。 每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。 在 Windows 系统中,Git 会查找 $HOME 目录下(一般情况下是 C:\Users\$USER)的 .gitconfig 文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。 3.1 用户信息配置每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改: 12$ git config --global user.name "mantoudev"$ git config --global user.email [email protected] 如果使用了 –global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 –global 选项的命令来配置。 很多 GUI 工具都会在第一次运行时帮助你配置这些信息。 3.2 检查配置信息如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。 12345678$ git config --listuser.name=mantoudevuser.email=mantoudev@163.comcolor.status=autocolor.branch=autocolor.interactive=autocolor.diff=auto... 你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig 与 ~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。 你可以通过输入 git config <key>: 来检查 Git 的某一项配置 12$ git config user.namemantoudev 4. 基本常用命令(1) 添加文件到暂存区(staged)123$ git add filename #或$ git stage filename (2) 将所有修改文件添加到暂存区(staged)123$ git add --all#或$ git add -A (3) 提交修改到暂存区(staged)12$ git commit -m 'commit message'$ git commit -a -m 'commit message' 注意理解 -a 参数的意义 (4) 从Git仓库中删除文件:1$ git rm filename (5) 从Git仓库中删除文件,但本地文件保留:1$ git rm --cached filename (6) 重命名某个文件: 123$ git mv filename newfilename#或者直接修改完毕文件名 ,进行$ git add -A && git commit -m 'commit message' Git会自动识别是重命名了文件 (7) 获取远程最新代码到本地:1$ git pull (origin branchname) 可以指定分支名,也可以忽略。pull 命令自动 fetch 远程代码并且 merge,如果有冲突,会显示在状态栏,需要手动处理。更推荐使用:git fetch 之后 git merge --no-ff origin branchname 拉取最新的代码到本地仓库,并手动 merge 。 5. Git commit messge规范查看Commit message 1$ git log <last tag> HEAD --pretty=format:%s 5.1 Commit Message格式每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。 12345<type>(<scope>): <subject>// 空一行<body>// 空一行<footer> 其中,Header 是必需的,Body 和 Footer 可以省略。不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。 5.2 HeaderHeader部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。 (1)typetype用于说明 commit 的类别,只允许使用下面7个标识。 feat:新功能(feature) fix:修补bug docs:文档(documentation) style: 格式(不影响代码运行的变动) refactor:重构(即不是新增功能,也不是修改bug的代码变动) test:增加测试 chore:构建过程或辅助工具的变动 revert: 撤销以前的 commit,后面跟着被撤销 Commit 的 Header。 (2)scopescope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。 (3)subjectsubject是 commit 目的的简短描述,不超过50个字符。 以动词开头,使用第一人称现在时,比如change,而不是changed或changes 第一个字母小写 结尾不加句号(.) 5.3 BodyBody 部分是对本次 commit 的详细描述,可以分成多行。下面是一个范例。 12345此次修改主要对****功能模块进行重构,包含以下部分:1. AAAAAAA....2. BBBBBBB....3. CCCCCCC.... body中还可以与一些Bug管理工具进行关联,在Header之后换行添加 1Bug: <Bug编号> 5.4 Footer(1)不兼容变动如果当前代码与上一个版本不兼容,则 Footer 部分以BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法。 1234567891011121314151617BREAKING CHANGE: isolate scope bindings definition has changed. To migrate the code follow the example below: Before: scope: { myAttr: 'attribute', } After: scope: { myAttr: '@', } The removed `inject` wasn't generaly useful for directives (2) 关闭 Issue如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue 。 1Closes #234 (3) 签名如果commit使用签名的话,footer中会包含签名信息 1Signed-off-by: mantoudev <[email protected]> (4) 其他使用gerrit(代码审查工具,gerrit维基百科),在footer中会生成一个ChanggeId,一个ChangeId标识一次内容变化,可以包含多个commit,即多个commit如果changeid一致的话,可以认为是一个change。 6. 乱码处理Linux 、MacOS默认编码为utf-8,windows默认编码为GBK。提交时编码不统一,或者展示时编码不统一,会出现乱码的情况。 6.1 git status时中文文件名乱码现象: 1\344\275\240\345\245\275 执行以下命令即可: 1git config --global core.quotepath false quotepath解释: 1The commands that output paths (e.g. ls-files, diff), when not given the -z option,will quote "unusual" characters in the pathname by enclosing the pathname in a double-quote pair and with backslashes the same way strings in C source code are quoted. If this variable is set to false, the bytes higher than 0x80 are not quoted but output as verbatim. Note that double quote, backslash and control characters are always quoted without -z regardless of the setting of this variable. 6.2 git log 查看提交中含中文乱码现象: 1<E4><BF><AE><E6> 修改git全局配置设置提交和查看日志编码都是utf-8 12git config --global i18n.commitencoding utf-8git config --global i18n.logoutputencoding utf-8 修改git目录下etc\profile文件,设置less的字符集为utf-8 1export LESSCHARSET=utf-8 (Windows)修改cmder目录vendor\init.bat文件,添加以下代码,设定cmder编码为utf-8 1@chcp 65001 > nul chcp 65001的解释: 1Why is there no option to choose codepage 65001 (UTF-8) as a default codepage in console window 6.3 gitk查看中文乱码解决办法: 1git config --global gui.encoding utf-8 7. 参考资料 Git-scm官方文档 猴子都能懂的Git系列 Git学习资料汇总]]></content>
<categories>
<category>Git</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
</search>