-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent.json
More file actions
1 lines (1 loc) · 40 KB
/
Copy pathcontent.json
File metadata and controls
1 lines (1 loc) · 40 KB
1
{"pages":[{"title":"Categories","date":"2018-08-20T02:17:49.262Z","path":"categories/index.html","text":""}],"posts":[{"title":"zookeeper 详解","date":"2018-10-25T07:01:55.379Z","path":"wiki/BigData/Zookeeper/ZooKeeper/","text":"前言相信大家对 ZooKeeper 应该不算陌生。但是你真的了解 ZooKeeper 是个什么东西吗?如果别人/面试官让你给他讲讲 ZooKeeper 是个什么东西,你能回答到什么地步呢? 我本人曾经使用过 ZooKeeper 作为 Dubbo 的注册中心,另外在搭建 solr 集群的时候,我使用到了 ZooKeeper 作为 solr 集群的管理工具。前几天,总结项目经验的时候,我突然问自己 ZooKeeper 到底是个什么东西?想了半天,脑海中只是简单的能浮现出几句话:“①Zookeeper 可以被用作注册中心。 ②Zookeeper 是 Hadoop 生态系统的一员;③构建 Zookeeper 集群的时候,使用的服务器最好是奇数台。” 可见,我对于 Zookeeper 的理解仅仅是停留在了表面。 所以,通过本文,希望带大家稍微详细的了解一下 ZooKeeper 。如果没有学过 ZooKeeper ,那么本文将会是你进入 ZooKeeper 大门的垫脚砖。如果你已经接触过 ZooKeeper ,那么本文将带你回顾一下 ZooKeeper 的一些基础概念。 最后,本文只涉及 ZooKeeper 的一些概念,并不涉及 ZooKeeper 的使用以及 ZooKeeper 集群的搭建。 网上有介绍 ZooKeeper 的使用以及搭建 ZooKeeper 集群的文章,大家有需要可以自行查阅。 一 什么是 ZooKeeperZooKeeper 的由来下面这段内容摘自《从Paxos到Zookeeper 》第四章第一节的某段内容,推荐大家阅读以下: Zookeeper最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。 关于“ZooKeeper”这个项目的名字,其实也有一段趣闻。在立项初期,考虑到之前内部很多项目都是使用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家RaghuRamakrishnan开玩笑地说:“在这样下去,我们这儿就变成动物园了!”此话一出,大家纷纷表示就叫动物园管理员吧一一一因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好要用来进行分布式环境的协调一一于是,Zookeeper的名字也就由此诞生了。 1.1 ZooKeeper 概览ZooKeeper 是一个开源的分布式协调服务,ZooKeeper框架最初是在“Yahoo!”上构建的,用于以简单而稳健的方式访问他们的应用程序。 后来,Apache ZooKeeper成为Hadoop,HBase和其他分布式框架使用的有组织服务的标准。 例如,Apache HBase使用ZooKeeper跟踪分布式数据的状态。ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。 原语: 操作系统或计算机网络用语范畴。是由若干条指令组成的,用于完成一定功能的一个过程。具有不可分割性·即原语的执行必须是连续的,在执行过程中不允许被中断。 ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。 Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。如下图所示,在 Dubbo架构中 Zookeeper 就担任了注册中心这一角色。 1.2 结合个人使用情况的讲一下 ZooKeeper在我自己做过的项目中,主要使用到了 ZooKeeper 作为 Dubbo 的注册中心(Dubbo 官方推荐使用 ZooKeeper注册中心)。另外在搭建 solr 集群的时候,我使用 ZooKeeper 作为 solr 集群的管理工具。这时,ZooKeeper 主要提供下面几个功能:1、集群管理:容错、负载均衡。2、配置文件的集中管理3、集群的入口。 我个人觉得在使用 ZooKeeper 的时候,最好是使用 集群版的 ZooKeeper 而不是单机版的。官网给出的架构图就描述的是一个集群版的 ZooKeeper 。通常 3 台服务器就可以构成一个 ZooKeeper 集群了。 为什么最好使用奇数台服务器构成 ZooKeeper 集群? 所谓的zookeeper容错是指,当宕掉几个zookeeper服务器之后,剩下的个数必须大于宕掉的个数的话整个zookeeper才依然可用。假如我们的集群中有n台zookeeper服务器,那么也就是剩下的服务数必须大于n/2。先说一下结论,2n和2n-1的容忍度是一样的,都是n-1,大家可以先自己仔细想一想,这应该是一个很简单的数学问题了。比如假如我们有3台,那么最大允许宕掉1台zookeeper服务器,如果我们有4台的的时候也同样只允许宕掉1台。假如我们有5台,那么最大允许宕掉2台zookeeper服务器,如果我们有6台的的时候也同样只允许宕掉2台。 综上,何必增加那一个不必要的zookeeper呢? 二 关于 ZooKeeper 的一些重要概念2.1 重要概念总结 ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务)。 为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么 ZooKeeper 本身仍然是可用的。 ZooKeeper 将数据保存在内存中,这也就保证了 高吞吐量和低延迟(但是内存限制了能够存储的容量不太大,此限制也是保持znode中存储的数据量较小的进一步原因)。 ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。) ZooKeeper有临时节点的概念。 当创建临时节点的客户端会话一直保持活动,瞬时节点就一直存在。而当会话终结时,瞬时节点被删除。持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上。 ZooKeeper 底层其实只提供了两个功能:①管理(存储、读取)用户程序提交的数据;②为用户程序提交数据节点监听服务。 下面关于会话(Session)、 Znode、版本、Watcher、ACL概念的总结都在《从Paxos到Zookeeper 》第四章第一节以及第七章第八节有提到,感兴趣的可以看看! 2.2 会话(Session)Session 指的是 ZooKeeper 服务器与客户端会话。在 ZooKeeper 中,一个客户端连接是指客户端和服务器之间的一个 TCP 长连接。客户端启动的时候,首先会与服务器建立一个 TCP 连接,从第一次连接建立开始,客户端会话的生命周期也开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知。 Session的sessionTimeout值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在sessionTimeout规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。 在为客户端创建会话之前,服务端首先会为每个客户端都分配一个sessionID。由于 sessionID 是 Zookeeper 会话的一个重要标识,许多与会话相关的运行机制都是基于这个 sessionID 的,因此,无论是哪台服务器为客户端分配的 sessionID,都务必保证全局唯一。 2.3 Znode在谈到分布式的时候,我们通常说的“节点”是指组成集群的每一台机器。然而,在Zookeeper中,“节点”分为两类,第一类同样是指构成集群的机器,我们称之为机器节点;第二类则是指数据模型中的数据单元,我们称之为数据节点一一ZNode。 Zookeeper将所有数据存储在内存中,数据模型是一棵树(Znode Tree),由斜杠(/)的进行分割的路径,就是一个Znode,例如/foo/path1。每个上都会保存自己的数据内容,同时还会保存一系列属性信息。 在Zookeeper中,node可以分为持久节点和临时节点两类。所谓持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上。而临时节点就不一样了,它的生命周期和客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。另外,ZooKeeper还允许用户为每个节点添加一个特殊的属性:SEQUENTIAL.一旦节点被标记上这个属性,那么在这个节点被创建的时候,Zookeeper会自动在其节点名后面追加上一个整型数字,这个整型数字是一个由父节点维护的自增数字。 2.4 版本在前面我们已经提到,Zookeeper 的每个 ZNode 上都会存储数据,对应于每个ZNode,Zookeeper 都会为其维护一个叫作 Stat 的数据结构,Stat中记录了这个 ZNode 的三个数据版本,分别是version(当前ZNode的版本)、cversion(当前ZNode子节点的版本)和 cversion(当前ZNode的ACL版本)。 2.5 WatcherWatcher(事件监听器),是Zookeeper中的一个很重要的特性。Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。 2.6 ACLZookeeper采用ACL(AccessControlLists)策略来进行权限控制,类似于 UNIX 文件系统的权限控制。Zookeeper 定义了如下5种权限。 其中尤其需要注意的是,CREATE和DELETE这两种权限都是针对子节点的权限控制。 三 ZooKeeper 特点 顺序一致性: 从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。 原子性: 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。 单一系统映像 : 无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。 可靠性: 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。 四 ZooKeeper 设计目标4.1 简单的数据模型ZooKeeper 允许分布式进程通过共享的层次结构命名空间进行相互协调,这与标准文件系统类似。 名称空间由 ZooKeeper 中的数据寄存器组成 - 称为znode,这些类似于文件和目录。 与为存储设计的典型文件系统不同,ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟。 4.2 可构建集群为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么zookeeper本身仍然是可用的。 客户端在使用 ZooKeeper 时,需要知道集群机器列表,通过与集群中的某一台机器建立 TCP 连接来使用服务,客户端使用这个TCP链接来发送请求、获取结果、获取监听事件以及发送心跳包。如果这个连接异常断开了,客户端可以连接到另外的机器上。 ZooKeeper 官方提供的架构图: 上图中每一个Server代表一个安装Zookeeper服务的服务器。组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 Zab 协议(Zookeeper Atomic Broadcast)来保持数据的一致性。 4.3 顺序访问对于来自客户端的每个更新请求,ZooKeeper 都会分配一个全局唯一的递增编号,这个编号反应了所有事务操作的先后顺序,应用程序可以使用 ZooKeeper 这个特性来实现更高层次的同步原语。 这个编号也叫做时间戳——zxid(Zookeeper Transaction Id) 4.4 高性能ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。) 五 ZooKeeper 集群角色介绍最典型集群模式: Master/Slave 模式(主备模式)。在这种模式中,通常 Master服务器作为主服务器提供写服务,其他的 Slave 服务器从服务器通过异步复制的方式获取 Master 服务器最新的数据提供读服务。 但是,在 ZooKeeper 中没有选择传统的 Master/Slave 概念,而是引入了Leader、Follower 和 Observer 三种角色。如下图所示 ZooKeeper 集群中的所有机器通过一个 Leader 选举过程来选定一台称为 “Leader” 的机器,Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,Follower 和 Observer 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。 当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进人恢复模式并选举产生新的Leader服务器。这个过程大致是这样的: Leader election(选举阶段):节点在一开始都处于选举阶段,只要有一个节点得到超半数节点的票数,它就可以当选准 leader。 Discovery(发现阶段):在这个阶段,followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。 Synchronization(同步阶段):同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后准 leader 才会成为真正的 leader。 Broadcast(广播阶段)到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步。 六 ZooKeeper &ZAB 协议&Paxos算法6.1 ZAB 协议&Paxos算法Paxos 算法应该可以说是 ZooKeeper 的灵魂了。但是,ZooKeeper 并没有完全采用 Paxos算法 ,而是使用 ZAB 协议作为其保证数据一致性的核心算法。另外,在ZooKeeper的官方文档中也指出,ZAB协议并不像 Paxos 算法那样,是一种通用的分布式一致性算法,它是一种特别为Zookeeper设计的崩溃可恢复的原子消息广播算法。 6.2 ZAB 协议介绍ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。 6.3 ZAB 协议两种基本的模式:崩溃恢复和消息广播ZAB协议包括两种基本的模式,分别是 崩溃恢复和消息广播。当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进人恢复模式并选举产生新的Leader服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该Leader服务器完成了状态同步之后,ZAB协议就会退出恢复模式。其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致。 当集群中已经有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个服务框架就可以进人消息广播模式了。 当一台同样遵守ZAB协议的服务器启动后加人到集群中时,如果此时集群中已经存在一个Leader服务器在负责进行消息广播,那么新加人的服务器就会自觉地进人数据恢复模式:找到Leader所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。正如上文介绍中所说的,ZooKeeper设计成只允许唯一的一个Leader服务器来进行事务请求的处理。Leader服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议;而如果集群中的其他机器接收到客户端的事务请求,那么这些非Leader服务器会首先将这个事务请求转发给Leader服务器。 关于 ZAB 协议&Paxos算法 需要讲和理解的东西太多了,说实话,笔主到现在不太清楚这俩兄弟的具体原理和实现过程。推荐阅读下面两篇文章: 图解 Paxos 一致性协议 Zookeeper ZAB 协议分析 关于如何使用 zookeeper 实现分布式锁,可以查看下面这篇文章: 10分钟看懂!基于Zookeeper的分布式锁 六 总结通过阅读本文,想必大家已从 ①ZooKeeper的由来。 -> ②ZooKeeper 到底是什么 。-> ③ ZooKeeper 的一些重要概念(会话(Session)、 Znode、版本、Watcher、ACL)-> ④ZooKeeper 的特点。 -> ⑤ZooKeeper 的设计目标。-> ⑥ ZooKeeper 集群角色介绍 (Leader、Follower 和 Observer 三种角色)-> ⑦ZooKeeper &ZAB 协议&Paxos算法。 这七点了解了 ZooKeeper 。 参考 《从Paxos到Zookeeper 》 https://cwiki.apache.org/confluence/display/ZOOKEEPER/ProjectDescription https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index https://www.cnblogs.com/raphael5200/p/5285583.html https://zhuanlan.zhihu.com/p/30024403","tags":[],"categories":[{"name":"BigData","slug":"BigData","permalink":"https://wiki.51itzone.cn/categories/BigData/"},{"name":"Zookeeper","slug":"BigData/Zookeeper","permalink":"https://wiki.51itzone.cn/categories/BigData/Zookeeper/"}]},{"title":"数据结构基本概念","date":"2018-10-10T08:29:10.867Z","path":"wiki/Algorithm/DataStructure/data-structure/","text":"什么是数据结构在计算机科学中,数据结构(data structure)是表示计算机中存储、组织数据的方式,逻辑结构和物理存储结构。 解决问题方法的效率: 跟数据的组织方式有关 跟空间的利用效率有关 跟算法的巧妙程度有关 数据结构的基本功能 如何插入一条新的数据项 如何寻找某一特定的数据项 如何删除某一特定的数据项 如何迭代的访问各个数据项,以便进行显示或其他操作 抽象数据类型(ADT)在编程语言中,常见的几个抽象数据类型如下: 数组 链表 队列 堆栈 字符串 树 图 时间复杂度常见的时间复杂度量级有: 常数阶O(1)对数阶O(logN)线性阶O(n)线性对数阶O(nlogN)平方阶O(n²)立方阶O(n³)K次方阶O(n^k)指数阶(2^n) 空间复杂度 参考资料 抽象数据类型","tags":[],"categories":[{"name":"Algorithm","slug":"Algorithm","permalink":"https://wiki.51itzone.cn/categories/Algorithm/"},{"name":"DataStructure","slug":"Algorithm/DataStructure","permalink":"https://wiki.51itzone.cn/categories/Algorithm/DataStructure/"}]},{"title":"Git 笔记","date":"2018-08-30T11:36:14.741Z","path":"wiki/BasicSkills/GitNotes/","text":"Git介绍 Git是分布式版本控制系统 集中式VS分布式,SVN VS Git SVN 和 Git 主要的区别在于历史版本维护的位置 Git 本地仓库包含代码库还有历史库,在本地的环境开发就可以记录历史而SVN的历史库存在于中央仓库,每次对比与提交代码都必须连接到中央仓库才能进行。 这样的好处在于: 自己可以在脱机环境查看开发的版本历史。 多人开发时如果充当中央仓库的 Git 仓库挂了,可以随时创建一个新的中央仓库然后同步就立刻恢复了中央库。 Git命令Git配置12git config --global user.name \"Your Name\"git config --global user.email \"email@example.com\" git config 命令的 --global 参数,表明这台机器上的所有 Git 仓库都会使用这个配置,也可以对某个仓库指定不同的用户名和邮箱地址。 创建版本库初始化一个Git仓库1git init 添加文件到Git仓库包括两步: 12git add <file>git commit -m \"description\" git add 可以反复多次使用,添加多个文件,git commit 可以一次提交很多文件,-m 后面输入的是本次提交的说明,可以输入任意内容。 查看工作区状态1git status 查看修改内容1git diff 1git diff --cached 1git diff HEAD -- <file> git diff 可以查看工作区(work dict)和暂存区(stage)的区别 git diff --cached 可以查看暂存区(stage)和分支(master)的区别 git diff HEAD -- <file> 可以查看工作区和版本库里面最新版本的区别 查看提交日志1git log 简化日志输出信息 1git log --pretty=oneline 查看命令历史1git reflog 版本回退1git reset --hard HEAD^ 以上命令是返回上一个版本,在Git中,用 HEAD 表示当前版本,上一个版本就是 HEAD^ ,上上一个版本是 HEAD^^ ,往上100个版本写成 HEAD~100。 回退指定版本号1git reset --hard commit_id commit_id 是版本号,是一个用 SHA1 计算出的序列 工作区、暂存区和版本库工作区:在电脑里能看到的目录;版本库:在工作区有一个隐藏目录 .git,是Git的版本库。Git的版本库中存了很多东西,其中最重要的就是称为 stage(或者称为 index )的暂存区,还有 Git 自动创建的 master,以及指向 master 的指针 HEAD。 进一步解释一些命令: git add 实际上是把文件添加到暂存区 git commit 实际上是把暂存区的所有内容提交到当前分支 撤销修改丢弃工作区的修改1git checkout -- <file> 该命令是指将文件在工作区的修改全部撤销,这里有两种情况: 一种是 file 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态; 一种是 file 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。 总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。 丢弃暂存区的修改分两步:第一步,把暂存区的修改撤销掉(unstage),重新放回工作区: 1git reset HEAD <file> 第二步,撤销工作区的修改 1git checkout -- <file> 小结: 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout -- <file>。 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令 git reset HEAD <file>,就回到了第一步,第二步按第一步操作。 已经提交了不合适的修改到版本库时,想要撤销本次提交,进行版本回退,前提是没有推送到远程库。 删除文件1git rm <file> git rm <file> 相当于执行 12rm <file>git add <file> 进一步的解释Q:比如执行了 rm text.txt 误删了怎么恢复?A:执行 git checkout -- text.txt 把版本库的东西重新写回工作区就行了Q:如果执行了 git rm text.txt 我们会发现工作区的 text.txt 也删除了,怎么恢复?A:先撤销暂存区修改,重新放回工作区,然后再从版本库写回到工作区 12git reset head text.txtgit checkout -- text.txt Q:如果真的想从版本库里面删除文件怎么做?A:执行 git commit -m "delete text.txt" ,提交后最新的版本库将不包含这个文件 远程仓库创建 SSH Key1ssh-keygen -t rsa -C \"youremail@example.com\" 关联远程仓库1git remote add origin https://github.com/username/repositoryname.git 推送到远程仓库1git push -u origin master -u 表示第一次推送 master 分支的所有内容,此后,每次本地提交后,只要有必要,就可以使用命令 git push origin master 推送最新修改。 从远程克隆1git clone https://github.com/usern/repositoryname.git 修改远程仓库地址1git remote set-url origin https://github.com/usern/repositoryname.git 或先删除后加 12git remote rm origingit remote add origin https://github.com/usern/repositoryname.git 分支创建分支1git branch <branchname> 查看分支1git branch git branch 命令会列出所有分支,当前分支前面会标一个 * 号。 切换分支1git checkout <branchname> 创建+切换分支1git checkout -b <branchname> 合并某分支到当前分支1git merge <branchname> 删除分支1git branch -d <branchname> 查看分支合并图1git log --graph 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。用 git log --graph 命令可以看到分支合并图。 普通模式合并分支1git merge --no-ff -m \"description\" <branchname> 因为本次合并要创建一个新的commit,所以加上 -m 参数,把commit描述写进去。合并分支时,加上 --no-ff 参数就可以用普通模式合并,能看出来曾经做过合并,包含作者和时间戳等信息,而fast forward合并就看不出来曾经做过合并。 保存工作现场1git stash 查看工作现场1git stash list 恢复工作现场1git stash pop 丢弃一个没有合并过的分支1git branch -D <branchname> 查看远程库信息1git remote -v 在本地创建和远程分支对应的分支1git checkout -b branch-name origin/branch-name, 本地和远程分支的名称最好一致; 建立本地分支和远程分支的关联1git branch --set-upstream branch-name origin/branch-name; 从本地推送分支1git push origin branch-name 如果推送失败,先用 git pull抓取远程的新提交; 从远程抓取分支1git pull 如果有冲突,要先处理冲突。 Github fork 出来的分支与主库保持同步12345git remote add upstream https://github.com/usern/repositoryname.gitgit fetch upstreamgit checkout mastergit merge upstream/master 标签tag 就是一个让人容易记住的有意义的名字,它跟某个 commit 绑在一起。 新建一个标签1git tag <tagname> 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个 commit id。 指定标签信息1git tag -a <tagname> -m <description> <branchname> or commit_id git tag -a <tagname> -m "blablabla..."可以指定标签信息。 PGP签名标签1git tag -s <tagname> -m <description> <branchname> or commit_id git tag -s <tagname> -m "blablabla..." 可以用 PGP 签名标签。 查看所有标签1git tag 推送一个本地标签1git push origin <tagname> 推送全部未推送过的本地标签1git push origin --tags 删除一个本地标签1git tag -d <tagname> 删除一个远程标签1git push origin :refs/tags/<tagname> git 分支开发最佳实践 子模块 submodulegit Submodule 是一个很好的多项目使用共同类库的工具,他允许类库项目做为 repository ,子项目做为一个单独的 git 项目存在父项目中,子项目可以有自己的独立的commit,push,pull。而父项目以Submodule的形式包含子项目,父项目可以指定子项目 header ,父项目中会的提交信息包含 Submodule 的信息,再 clone 父项目的时候可以把 Submodule 初始化。 添加 Submodule1git submodule add git@github.com:usern/repositoryname.git folder 更新 Submodule在父目录下更新 1git submodule foreach git pull 在 Submodule 目录下更新 12cd foldergit pull 克隆含有子模块的项目采用递归参数 --recursive 1git clone git@github.com:usern/repositoryname.git --recursive 先 clone 父目录,再初始化 Submodule 1234git clone git@github.com:usern/repositoryname.gitcd repositorynamegit submodule initgit submodule init 删除 Submodule1234git rm --cached repositorynamerm -rf repositorynamerm .gitmodulesgit commit -a -m 'remove repositoryname submodule'","tags":[],"categories":[{"name":"BasicSkills","slug":"BasicSkills","permalink":"https://wiki.51itzone.cn/categories/BasicSkills/"}]},{"title":"ES 分词器","date":"2018-08-29T02:50:32.125Z","path":"wiki/BigData/Elsatic/tokenizer/","text":"分词器","tags":[],"categories":[{"name":"BigData","slug":"BigData","permalink":"https://wiki.51itzone.cn/categories/BigData/"},{"name":"Elsatic","slug":"BigData/Elsatic","permalink":"https://wiki.51itzone.cn/categories/BigData/Elsatic/"}]},{"title":"RabbitMQ 详解","date":"2018-08-20T02:25:16.296Z","path":"wiki/DistributedSystem/Rabbitmq/rabbitmq/","text":"channel 参数详解basicPublish 方法12345678910111213141516171819202122/** * Publish a message. * * Publishing to a non-existent exchange will result in a channel-level * protocol exception, which closes the channel. * * Invocations of <code>Channel#basicPublish</code> will eventually block if a * <a href=\"http://www.rabbitmq.com/alarms.html\">resource-driven alarm</a> is in effect. * * @see com.rabbitmq.client.AMQP.Basic.Publish * @see <a href=\"http://www.rabbitmq.com/alarms.html\">Resource-driven alarms</a>. * @param exchange the exchange to publish the message to * @param routingKey the routing key * @param mandatory true if the 'mandatory' flag is to be set * @param immediate true if the 'immediate' flag is to be * set. Note that the RabbitMQ server does not support this flag. * @param props other properties for the message - routing headers etc * @param body the message body * @throws java.io.IOException if an error is encountered */ void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException; basicAckdeliveryTag: 该消息的indexmultiple:是否批量.true: 将一次性 ack 所有小于 deliveryTag 的消息。 basicNackchannel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, true); deliveryTag: 该消息的 indexmultiple:是否批量.true: 将一次性拒绝所有小于 deliveryTag 的消息。requeue:被拒绝的是否重新入队列 basicRejectchannel.basicReject(delivery.getEnvelope().getDeliveryTag(), false); deliveryTag: 该消息的 indexrequeue:被拒绝的是否重新入队列 channel.basicNack 与 channel.basicReject 的区别: basicNack可以拒绝多条消息,而basicReject一次只能拒绝一条消息","tags":[],"categories":[{"name":"DistributedSystem","slug":"DistributedSystem","permalink":"https://wiki.51itzone.cn/categories/DistributedSystem/"},{"name":"Rabbitmq","slug":"DistributedSystem/Rabbitmq","permalink":"https://wiki.51itzone.cn/categories/DistributedSystem/Rabbitmq/"}]},{"title":"Python 基础","date":"2018-08-20T02:17:49.260Z","path":"wiki/ProgrammingLanguage/Python/python_learn/","text":"什么是 Python 解释器?Python 解析器提供了程序的运行环。Python 是解析执行的,与C/C++之类的编译性语言编写的程序类比,Python 源码不需要从源文件转换成计算机使用的机器语言,也不需要经过连接器链接之后形成二进制可执行文件。当我们运行 Python 程序的时候,Python 解析器将源码转换为字节码,然后再由 Python 解析器来执行这些字节码。但是,Python 程序每次运行都需要转换成字节码,然后再由虚拟机把字节码转换成机器语言,最后才能在硬件上运行。与编译性语言相比,每次多出了编译和链接的过程,性能会受到一定的影响。 官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行 python 命令就是启动 CPython 解释器。 什么是编译型语言和解释型语言 编译型语言实现的,如:C、C++、Fortran、Pascal、Ada。由编译型语言编写的源程序需要经过编译,汇编和链接才能输出目标代码,然后由机器加载到内存中执行目标代码。目标代码是有机器指令组成,不能独立运行,因为源程序中可能使用了一些汇编程序不能解释引用的库函数,而库函数又不在源程序中,此时还需要链接程序完成外部引用和目标模板调用的链接任务,最后才能输出可执行代码。 解释型语言,解释器不产生目标机器代码,而是产生中间代码,这种中间代码与机器代码不同,中间代码的解释是由软件支持的,不能直接使用在硬件上。该软件解释器通常会导致执行效率较低,用解释型语言编写的程序是由另一个可以理解中间代码的解释程序执行的。和编译的程序不同的是, 解释程序的任务是逐一将源代码的语句解释成可执行的机器指令,不需要将源程序翻译成目标代码再执行。对于解释型语言,需要一个专门的解释器来执行该程序, 每条语句只有在执行是才能被翻译,这种解释型语言每执行一次就翻译一次,因而效率低下。 Java 解释器,也称 Java 虚拟机, Java 程序是需要编译的,但是没有直接编译成机器语言,而是编译成字节码, 然后在 Java 虚拟机上用解释的方式执行 Java 字节码。Python 也使用了类似的方式,先将 Python 编译成 Python 字节码,然后由一个专门的 Python 字节码解释器负责解释执行字节码。 Python 是一门解释语言,但是出于效率的考虑,提供了一种编译的方法。编译之后就得到 pyc 文件,存储了字节码。Python 这点和 Java 很类似,但是Java 与 Python 不同的是,Python 是一个解释型的语言,所以编译字节码不是一个强制的操作,事实上,编译是一个自动的过程,一般不会在意它的存在。编译成字节码可以节省加载模块的时间,提高效率。","tags":[],"categories":[{"name":"ProgrammingLanguage","slug":"ProgrammingLanguage","permalink":"https://wiki.51itzone.cn/categories/ProgrammingLanguage/"},{"name":"Python","slug":"ProgrammingLanguage/Python","permalink":"https://wiki.51itzone.cn/categories/ProgrammingLanguage/Python/"}]},{"title":"栈和队列","date":"2018-08-20T02:17:49.259Z","path":"wiki/Algorithm/DataStructure/stcak-and-queue/","text":"栈队列","tags":[],"categories":[{"name":"Algorithm","slug":"Algorithm","permalink":"https://wiki.51itzone.cn/categories/Algorithm/"},{"name":"DataStructure","slug":"Algorithm/DataStructure","permalink":"https://wiki.51itzone.cn/categories/Algorithm/DataStructure/"}]},{"title":"kafka 详解","date":"2018-08-20T02:17:49.257Z","path":"wiki/BigData/Kafka/kafka/","text":"kafka 应用场景kafka 作为时下最流行的开源消息系统,被广泛地应用在数据缓冲、异步通信、汇集日志、系统解耦等方面 kafka 如何实现每秒几十万的高并发写入Kafka 是高吞吐低延迟的高并发、高性能的消息中间件,在大数据领域有极为广泛的运用。配置良好的 Kafka 集群甚至可以做到每秒几十万、上百万的超高并发读取和写入。 页面缓存技术kafka 为了保证数据写入性能,基于操作系统的页缓存(page cache 为了处理块设备和内存交互时高速访问的问题)来实现文件写入。 磁盘顺序写零拷贝技术 参考资料 Linux 内核的文件 Cache 管理机制介绍 Page Cache Linux系统中的Page cache和Buffer cache","tags":[],"categories":[{"name":"BigData","slug":"BigData","permalink":"https://wiki.51itzone.cn/categories/BigData/"},{"name":"Kafka","slug":"BigData/Kafka","permalink":"https://wiki.51itzone.cn/categories/BigData/Kafka/"}]},{"title":"Welcome Javmain's Wiki","date":"2018-08-20T02:17:49.255Z","path":"wiki/index/","text":"这是 Javmain 的个人 Wiki 站点,主要记录学习遇到知识点。 我一直觉得 知识不能碎片化,要结构化,于是希望寻找一种优雅的方式来管理我的知识。 先后了解或尝试过 OneNote、Evernote、Blog、Wiki 等方式,总结了一套觉得比较合理的知识获取吸收管理流程: 通过网页、RSS、微信等网络渠道作为知识获取来源。 通过笔记系统(手写笔记、OneNote、Evernote)初步筛选有价值有针对性的信息,收藏信息,分类整理,做读后要点笔记记录。 自己平时突然想到或总结的一两句话,或很零碎的点子、灵感,初步消化的内容,则用 Wiki 记录。 最后当 Wiki 在某版块有一定量后,将这方面笔记和 Wiki 中的内容重读,整理和提炼,二次消化精炼再加上自己的感悟和理解,写成文章发表在 博客 上。 在使用中,笔记系统 主大块信息的分类和整理,Wiki 主零碎知识的积累,而 博客 只在于 精。 Wiki 中某一版块刚建时,可能只有很少内容或者就一句话,但是通过这种使用流程,日积月累,这方面的事物接触得多了,零散的知识也就多了,那么 Wiki 中这个版块记录的内容也就会变多了,也就是通过积累,把原本大量碎片化的知识结构化整理起来了。 博客的目的是 分享和展示,分享自己的知识,展示自己的水平,需要放拿得出手的东西,因此不适合放碎片化的只言片语,更适合放 一个系列 的总结或者教程等,是一个十分成体系的知识平台。 欢迎大家访问我的博客 Javmain’s Blog","tags":[],"categories":[]},{"title":"线性代数基础","date":"2018-08-20T02:17:49.255Z","path":"wiki/MachineLeaning/math/LinearAlgebra/LinearAlgebraBasic/","text":"线性代数是现代数学的基础之一,在物理、计算机图形学、工程、经济学等自然科学和社会科学各领域具有广泛和深刻的应用,同时线性代数是高等学校理工科各专业的一门重要基础课。本课程介绍求解线性方程组、矩阵理论、向量空间和线性变换等线性代数的基本概念和基本理论,强调线性代数的理论与应用的结合。通过本课程的学习,培养学生的数学逻辑思维和抽象思维能力,使学生具备线性代数的基本理论知识,熟练掌握求解线性方程组和矩阵运算、矩阵分解的基本方法,掌握英文数学术语和表达规范,为后继的学习和提高奠定数学基础。 线性代数(1)围绕求解线性方程组,介绍高斯消元法、矩阵的性质运算和分解、向量空间、正交投影与最小二乘法、行列式的性质与计算、特征值特征向量与矩阵对角化、实对称矩阵的性质等基本知识点。线性代数(1)的知识模块顺序为 向量及其运算简介矩阵和线性方程组高斯消元法矩阵的运算矩阵的逆LU分解向量空间求解齐次线性方程组求解非齐次线性方程组线性无关、基与维数四个基本子空间的基和维数四个基本子空间的正交关系正交投影最小二乘法Gram-Schmidt正交化行列式的基本性质行列式的计算Cramer法则及行列式的几何意义特征值与特征向量矩阵的对角化在微分方程中的应用实对称矩阵 课程参考书有以下几本,其中第一本可做教材: (1)Gilbert Strang, Introduction to linear algebra, Fourth Edition, Wellesley-Cambridge Press, 2009. (2)G. Strang, 线性代数及其应用, 侯自新、郑仲三、张延伦译,南开大学出版社,1990. (3)David C. Lay, Linear Algebra and Its Applications, 机械工业出版社, 2004;中文版:线性代数及其应用(第3版),机械工业出版社,2005. (4)Carl D. Meyer, Matrix Analysis and Applied Linear Algebra, SIAM.","tags":[],"categories":[{"name":"MachineLeaning","slug":"MachineLeaning","permalink":"https://wiki.51itzone.cn/categories/MachineLeaning/"},{"name":"math","slug":"MachineLeaning/math","permalink":"https://wiki.51itzone.cn/categories/MachineLeaning/math/"},{"name":"LinearAlgebra","slug":"MachineLeaning/math/LinearAlgebra","permalink":"https://wiki.51itzone.cn/categories/MachineLeaning/math/LinearAlgebra/"}]}]}