61.大数据之旅——电信日志项目04

本文详细介绍了Linux中nc工具的安装与使用,以及Zookeeper集群的常用指令,包括查看服务状态、投票阶段、执行阶段等。接着深入探讨了二阶段提交(2PC)和Paxos算法,解释了其在分布式一致性中的作用,特别是Paxos如何解决一致性问题。文章最后提到了Zookeeper基于Paxos算法的优化,以及Avro的Schema定义和序列化机制,展现了在大数据项目中如何处理分布式通信和数据一致性。
摘要由CSDN通过智能技术生成

Linux nc安装


Linux nc 介绍和安装使用
NetCat,在网络工具中有“瑞士军刀”美誉,其有Windows和Linux的版本。因为它短小精悍(1.84版本也不过25k,旧版本或缩减版甚至更小)、功能实用,被设计为一个简单、可靠的网络工具,可通过TCP或UDP协议传输读写数据。同时,它还是一个网络应用Debug分析器,因为它可以根据需要创建各种不同类型的网络连接。

安装方法一:在线安装
1.如果是在线安装,则执行:

wget http://sourceforge.NET/projects/netcat/files/netcat/0.7.1/netcat-0.7.1-1.i386.rpm

如果是离线安装,先从下载地址: http://sourceforge.net/projects/netcat/files/netcat/0.7.1/netcat-0.7.1-1.i386.rpm/download
下载nc的rpm包,然后上传到虚拟机上。
2.执行:rpm -ihv netcat-0.7.1-1.i386.rpm
如果出现:

warning: netcat-0.7.1-1.i386.rpm: Header V3 DSA/SHA1 Signature, key ID b2d79fc1: NOKEY  
error: Failed dependencies:  
        libc.so.6 is needed by netcat-0.7.1-1.i386  
        libc.so.6(GLIBC_2.0) is needed by netcat-0.7.1-1.i386  
        libc.so.6(GLIBC_2.1) is needed by netcat-0.7.1-1.i386  
        libc.so.6(GLIBC_2.3) is needed by netcat-0.7.1-1.i386  

说明还需要安装nc的依赖软件包:glibc

3.通过yum源查看glibc相关的资源列表(需要联网),执行:yum list glibc*
如果在yum安装时,报错404错误,说明当前默认yum源连接不可用(一般默认是用国外的yum源),所以,需要更换yum源,换成国内的yum源。

4.通过yum安装glibc,执行:yum install glibc.i686

Preparing...                ########################################### [100%]  
   1:netcat                 ########################################### [100%]  
5.安装netcat包,执行:rpm -ihv netcat-0.7.1-1.i386.rpm
Preparing...                ########################################### [100%]  
   1:netcat                 ########################################### [100%] 

再次测试zookeeper的四字命令,会发现成功。

安装方法二:yum安装(推荐)
执行:

yum install -y nc

会自动将nc 以及依赖环境都安装完毕

Linux—Yum介绍
Yum(全称为 Yellow dog Updater, Modified)是一个Linux的Shell前端软件包管理器。基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。

Linux—RPM介绍
RPM包:可以在linux环境下被安装或被卸载的程序软件包。通过Linux的 rpm指令来进行安装或卸载。
rpm常用指令:
1.rpm -qa 查看所有已安装的rpm包
2.rpm -qa | grep xxx 根据xxx关键字查找rpm的安装信息
3.rpm -ivh xxx.rpm 安装某个rpm包
4.rpm -ev --nodeps mysql-libs-5.1.71-1.el6.x86_64

Linux—更换yum源

网易yum源比较常用,拿网易yum源举例
实现步骤:
1.进入yum源配置目录
执行:cd /etc/yum.repos.d
2.备份系统自带的yum源
执行:mv CentOS-Base.repo CentOS-Base.repo.bk
3.下载网易的yum源(需要联网):
执行:wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
4.下载完yum源后,执行下边命令更新yum配置,使操作立即生效
执行:yum makecache (这个时间会很长)

除了网易之外,国内还有其他不错的yum源,比如中科大和搜狐的
中科大的yum源:

wget http://centos.ustc.edu.cn/CentOS-Base.repo

sohu的yum源

wget http://mirrors.sohu.com/help/CentOS-Base-sohu.repo

Zookeeper集群指令


Zookeeper集群命令
可以通过Linux nc 工具来查看Zookeeper集群服务状态(掌握3个即可)

  1. 执行:echo stat|nc 127.0.0.1 2181
    查看哪个节点(想看哪个节点,就写那个节点的ip即可)被选择作为follower或者leader
    Clients:
    /127.0.0.1:407430
    Latency min/avg/max: 0/0/0
    Received: 2
    Sent: 1
    Connections: 1
    Outstanding: 0
    Zxid: 0x500000002
    Mode: follower
    Node count: 8

  2. 执行:echo ruok|nc 127.0.0.1 2181
    测试是否启动了该Server,若回复imok表示已经启动。

  3. echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
    clientPort=2181
    dataDir=/home/software/zookeeper-3.4.7/tmp/version-2
    dataLogDir=/home/software/zookeeper-3.4.7/tmp/version-2
    tickTime=2000
    maxClientCnxns=60
    minSessionTimeout=4000
    maxSessionTimeout=40000
    serverId=1
    initLimit=10
    syncLimit=5
    electionAlg=3
    electionPort=3888
    quorumPort=2888
    peerType=0

  4. echo kill | nc 127.0.0.1 2181 ,关掉server

  5. echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。

  6. echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。

  7. echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。

  8. echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。

  9. echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。

  10. echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。

  11. echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。

Zookeeper配置详解


在这里插入图片描述

2PC算法


分布式下的数据一致性问题
对于一个将数据副本分布在不同分布式节点上的系统来说,如果对第一个节点的数据进行了更新操作并且更新成功后,却没有使得第二个节点上的数据得到相应的更新,于是在对第二个节点的数据进行读取操作时,获取的依然是老数据(或称为脏数据),这就是典型的分布式数据不一致情况。

为了解决分布式一致性问题,在长期的探索研究过程中,涌现出了一大批经典的一致性协议和算法,其中最著名的就是二阶段提交协议、三阶段提交协议和Paxos算法。

2PC
2PC,是Two-Phase Commit的缩写,即二阶段提交,是计算机网络尤其是在数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。通常,二阶段提交协议也被认为是一种一致性协议,用来保证分布式系统数据的一致性。目前,绝大部分的关系型数据库都是采用二阶段提交协议来完成分布式事务处理的,利用该协议能够非常方便地完成所有分布式事务参与者的协调,统一决定事务的提交或回滚,从而能够有效地保证分布式数据一致性,因此二阶段提交协议被广泛地应用在许多分布式系统中。

提交过程
二阶段提交协议是将事务的提交过程分成了两个阶段来进行处理,其执行流程如下。
阶段一:提交事务请求+执行事务

  1. 事务询问。
    协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
  2. 执行事务。
    各参与者节点执行事务操作,并将Undo和Redo信息记入事务日志中。
  3. 各参与者向协调者反馈事务询问的响应。
    如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行;如果参与者没有成功执行事务,那么就反馈给协调者No响应,表示事务不可以执行。
    由于上面讲述的内容在形式上近似是协调者组织各参与者对一次事务操作的投票表态过程,因此二阶段提交协议的阶段一也被称为“投票阶段”,即各参与者投票表明是否要继续执行接下去的事务提交操作。

阶段二:事务提交
在阶段二中,协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作,正常情况下,包含以下两种可能。
执行事务提交
假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务提交。

  1. 发送提交请求。
    协调者向所有参与者节点发出Commit请求。
  2. 事务提交。
    参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。
  3. 反馈事务提交结果。
    参与者在完成事务提交之后,向协调者发送Ack消息。
  4. 完成事务。
    协调者接收到所有参与者反馈的Ack消息后,完成事务。
    中断事务
    假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈响应,那么就会中断事务。
  5. 发送回滚请求。
    协调者向所有参与者节点发出Rollback请求。
  6. 事务回滚。
    参与者接收到Rollback请求后,会利用其在阶段一中记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。
  7. 反馈事务回滚结果。
    参与者在完成事务回滚之后,向协调者发送Ack消息。
  8. 中断事务。
    协调者接收到所有参与者反馈的Ack消息后,完成事务中断。
    以上就是二阶段提交过程中,前后两个阶段分别进行的处理逻辑。简单地讲,二阶段提交将一个事务的处理过程分为了投票和执行两个阶段,其核心是对每个事务都采用先尝试后提交的处理方式,因此也可以将二阶段提交看作一个强一致性的算法,下图分别展示了二阶段提交过程中“事务提交”和“事务中断”两种场景下的交互流程。
    在这里插入图片描述
    优缺点
    二阶段提交协议的优点:原理简单,实现方便。
    二阶段提交协议的缺点:同步阻塞、单点问题、脑裂、太过保守。
    如果一个管理集群中,同时出现2个Leader或多个Leader,称为脑裂现象
    同步阻塞
    二阶段提交协议存在的最明显也是最大的一个问题就是同步阻塞,这会极大地限制分布式系统的性能。在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。

单点问题
在上面的讲解过程中,相信读者可以看出,协调者的角色在整个二阶段提交协议中起到了非常重要的作用。一旦协调者出现问题,那么整个二阶段提交流程将无法运转,更为严重的是,如果协调者是在阶段二中出现问题的话,那么其他参与者

太过保守
如果在协调者指示参与者进行事务提交询问的过程中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息的话,这时协调者只能依靠其自身的超时机制来判断是否需要中断事务,这样的策略显得比较保守。换句话说,二阶段提交协议没有设计较为完善的容错机制,任意一个节点的失败都会导致整个事务的失败。

Paxos算法


在这里插入图片描述
Leslie B. Lamport is an American computer scientist. Lamport is best known for his seminal work in distributed systems and as the initial developer of the document preparation system LaTeX. Leslie Lamport was the winner of the 2013 Turing Award for imposing clear, well-defined coherence on the seemingly chaotic behavior of distributed computing systems, in which several autonomous computers communicate with each other by passing messages. He devised important algorithms and developed formal modeling and verification protocols that improve the quality of real distributed systems. These contributions have resulted in improved correctness, performance, and reliability of computer systems.

Read more about Leslie Lamport’s extensive work and publication archive at: www.lamport.org.

Leslie Lamport(莱斯利·兰伯特)
Paxos算法的作者Leslie Lamport(莱斯利·兰伯特)及其对计算机科学尤其是分布式计算领域的杰出贡献。作为2013年的新科图灵奖得主,现年73岁的Lamport是计算机科学领域一位拥有杰出成就的传奇人物,其先后多次荣获ACM和IEEE以及其他各类计算机重大奖项。Lamport对时钟同步算法、面包店算法、拜占庭将军问题以及Paxos算法的创造性研究,极大地推动了计算机科学尤其是分布式计算的发展,全世界无数工程师得益于他的理论,其中Paxos算法的提出,正是Lamport多年的研究成果。

说起Paxos理论的发表,还有一段非常有趣的历史故事。Lamport早在1990年就已经将其对Paxos算法的研究论文The Part-Time Parliament提交给ACM TOCS Jnl.的评审委员会了,但是由于Lamport“创造性”地使用了故事的方式来进行算法的描述,导致当时委员会的工作人员没有一个能够正确地理解他对算法的描述,时任主编要求Lamport使用严谨的数据证明方式来描述该算法,否则他们将不考虑接受这篇论文。遗憾的是,Lamport并没有接收他们的建议,当然也就拒绝了对论文的修改,并撤销了对这篇论文的提交。在后来的一个会议上,Lamport还对此事耿耿于怀:“为什么这些搞理论的人一点幽默感也没有呢?”

幸运的是,还是有人能够理解Lamport那公认的令人晦涩的算法描述的。1996年,来自微软的Butler Lampson在WDAG96上提出了重新审视这篇分布式论文的建议,在次年的WDAG97上,麻省理工学院的Nancy Lynch也公布了其根据Lamport的原文重新修改后的Revisiting the Paxos Algorithm,“帮助”Lamport用数学的形式化术语定义并证明了Paxos算法。于是在1998年的ACM TOCS上,这篇延迟了9年的论文终于被接受了,也标志着Paxos算法正式被计算机科学接受并开始影响更多的工程师解决分布式一致性问题。

后来在2001年,Lamport本人也做出了让步,这次他放弃了故事的描述方式,而是使用了通俗易懂的语言重新讲述了原文,并发表了Paxos Made Simple——当然,Lamport甚为固执地认为他自己的表述语言没有歧义,并且也足够让人明白Paxos算法,因此不需要数学来协助描述,于是整篇文章还是没有任何数学符号。好在这篇文章已经能够被更多的人理解,相信绝大多数的Paxos爱好者也都是从这篇文章开始慢慢进入了Paxos的神秘世界。
由于Lamport个人自负固执的性格,使得Paxos理论的诞生可谓一波三折。关于Paxos理论的诞生过程,后来也成为了计算机科学领域被广泛流传的学术趣事。

拜占庭将军问题的提出
1982年,Lamport与另两人共同发表了论文The Byzantine Generals Problem,提出了一种计算机容错理论。在理论描述过程中,为了将所要描述的问题形象的表达出来,Lamport设想出了下面这样一个场景:

拜占庭帝国有许多支军队,不同军队的将军之间必须制订一个统一的行动计划,从而做出进攻或者撤退的决定,同时,各个将军在地理上都是被分隔开来的,只能依靠军队的通讯员来进行通讯。然而,在所有的通讯员中可能会存在叛徒,这些叛徒可以任意篡改消息,从而达到欺骗将军的目的。

这就是著名的“拜占庭将军问题”。实际上拜占庭将军问题是一个分布式环境下的协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。

Paxos算法的诞生
Lamport在1990年提出了一个理论上的一致性解决方案,同时给出了严格的数学证明。鉴于之前采用故事类比的方式成功的阐述了“拜占廷将军问题”,因此这次Lamport同样用心良苦地设想出了一个场景来描述这种一致性算法需要解决的问题,及其具体的解决过程:

在古希腊有一个叫做Paxos的小岛,岛上采用议会的形式来通过法令,议会中的议员通过信使进行消息的传递。值得注意的是,议员和信使都是兼职的,他们随时有可能会离开议会厅,并且信使可能会重复的传递消息,也可能一去不复返。因此,议会协议要保证在这种情况下法令仍然能够正确的产生,并且不会出现冲突。

这就是论文The Part-Time Parliament中提到的兼职议会,而Paxos算法名称的由来也是取自论文中提到的Paxos小岛。在这个论文中,Lamport压根没有说Paxos小岛是虚构出来的,而是煞有介事的说是考古工作者发现了Paxos议会事务的手稿,从这些手稿猜测Paxos人开展议会的方法。因此,在这个论文中,Lamport从问题的提出到算法的推演论证,通篇贯穿了对Paxos议会历史的描述。

算法陈述
Paxos算法实际上也是一个类2pc算法,而重点是引入了“过半性”的投票理念,通俗地讲就是少数服从多数的原则。此外,Paxos算法支持分布式节点角色之间的轮换,即当协调者出现问题后,参与者可以变成协调者工作。这极大地避免了分布式单点的出现,因此Paxos算法既解决了无限期等待问题,也提高了性能,是目前来说最优秀的分布式一致性协议之一。

zookeeper底层是基于paxos算法来改进。zookeeper用的 fast paxos算法。paxos算法可能会引起活锁问题。《The chubby lock service for loosely coupled for distributed system》
课外阅读
论文下载地址:
https://www.microsoft.com/en-us/research/publication/paxos-made-simple/?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fum%2Fpeople%2Flamport%2Fpubs%2Fpaxos-simple.pdf
在这里插入图片描述

Zookeeper观察者


观察者
在不影响写入性能的情况下缩放Zookeeper

虽然客户端直接连接到投票选举的Zookeeper成员执行良好,但这个架构很难扩展到大量的客户端。问题就是因为我么添加了更多的投票成员,写入性能下降。这是由于这样的事实:一个写入操作要求共识协议至少是整体的一半,因此投票的成本随着投票者越多会显著增加。

我们引入了一个新的Zookeeper节点类型叫做Observer,它帮助处理这个问题并进一步完善了Zookeeper的可扩展性。观察者不参与投票,它只监听投票的结果,不是导致了他们的共识协议。除了这个简单的区别,观察者精确的和追随者一样运行 - 客户端可能链接他们并发送读取和写入请求。观察者像追随者一样转发这些请求到领导者,而他们只是简单的等待监听投票的结果。正因为如此,我们可以尽可能多的增加观察者的数量,而不影响投票的性能。

观察这还有其他优势。因为他们不投票,他们不是Zookeeper整体的主要组件。因此他们可以故障,或者从集群断开连接,而不影响Zookeeper服务的可用性。对用户的好处是观察者可以连接到比追随者更不可靠的网络。事实上,观察者可以用于从其他数据中心和Zookeeper服务通信。观察者的客户端会看到快速的读取,因为所有的读取都在本地,并且写入导致最小的网络开销,因为投票协议所需的消息数量更小。

怎么使用观察者

使用观察者设置Zookeeper全员非常简单,只需要在原来的配置文件上改两个地方。第一,在要设置的那个节点的配置文件设置为观察者,必须放置这一行:
peerType=observer
在这里插入图片描述

Zookeeper插件


在这里插入图片描述

Zookeeper特性


数据一致性
client不论连接到哪个Zookeeper,展示给它都是同一个视图,即查询的数据都是一样的。这是zookeeper最重要的性能。

原子性
对于事务决议的更新,只能是成功或者失败两种可能,没有中间状态。要么都更新成功,要么都不更新。即,要么整个集群中所有机器都成功应用了某一事务,要么都没有应用,一定不会出现集群中部分机器应用了改事务,另外一部分没有应用的情况。

可靠性
一旦服务端成功的应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直保留下来,除非有另一个事务又对其进行了改变。

实时性
Zookeeper保证客户端将在非常短的时间间隔范围内获得服务器的更新信息,或者服务器失效的信息,或者指定监听事件的变化信息。(前提条件是:网络状况良好)

顺序性
如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布。

过半性
zookeeper集群必须有半数以上的机器存活才能正常工作。因为只有满足过半数,才能满足选举机制选出Leader。因为只有过半,在做事务决议时,事务才能更新

Java原生序列化和反序列化


序列化
Person对象代码(注意要实现Serializable接口):

public class Person implements Serializable{
   
 
private String name;
 
private int age;
 
public String getName() {
   
return name;
}
 
public void setName(String name) {
   
this.name = name;
}
 
public int getAge() {
   
return age;
}
 
public void setAge(int age) {
   
this.age = age;
}
 
 
}

测试代码:

/*这个方法是测试Person对象序列化的,利用的是java提供的原生序列化机制
 *主要掌握的是ObjectOutputStream.writeObject()方法
 *需要注意的是被序列化的对象要实现Serializabel接口
*/
public void testSerialize01() throws Exception{
   
Person p=new Person();
p.setAge(23);
p.setName("jary");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("person.data"));
oos.writeObject(p);
oos.flush();
oos.close();
}

反序列化
测试代码:

/*这个方法是测试Person对象反序列化的,利用的是java原生提供的反序列
 * 需要掌握的是ObjectInputStream.readObject()方法
 */
@Test
public void testDeserialize01() throws Exception{
   
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("person.data"));
Person p =(Person) ois.readObject();
System.out.println(p.getAge());
System.out.println(p.getName());
}

三、SerializableId的作用
测试代码:

/*
 * 这个方法是测试SerializeId的作用
 * 当Person对象序列化完毕后,如果更改Person类的结构,比如新增一个私有属性等,再次反序列化时会报错。
 * 原因是:当序列化时,会自动生成一个SerializeId,反序列化时,也会生成一个SerializeId,如果更改了Person对    象会导致两个SerializeId不一样,从而反序列化失败。
 * 所以解决办法是:手动加上SerializeId
 */
@Test
public void testSerializeId() throws Exception{
   
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("person.data"));
Person p =(Person) ois.readObject();
System.out.println(p.getAge());
System.out.println(p.getName());
 
}

Person代码:

public class Person implements Serializable{
   
 
private static final long serialVersionUID = 1500208610485192912L;
 
private String name;
 
private int age;
 
public String getName() {
   
return name;
}
 
public void setName(String name) {
   
this.name = name;
}
 
public int getAge() {
   
return age;
}
 
public void setAge(int age) {
   
this.age = age;
}
 
 
}

四、SerializableId的作用
在某些场景下,对于某些字段我们不想序列化,出于安全的角度,比如密码。此时,我们就可以用transient关键字,在序列化时忽略此字段。
示例代码:

public class Person implements Serializable{
   
private static final long serialVersionUID = 1500208610485192912L;
private String name;
private int age;
private transient String password;

五、总结Java原生序列化
1.java原生序列化在实际开发中用的非常少,因为序列化完后的数据文件很大。
2.不能跨语言。java序列化后的数据文件,不能用c语言或其他语言还原回来
3.速度慢
4.java的序列化机制在每个类的对象第一次出现的时候保存了每个类的信息, 比如类名, 第二次出现的类对象会有一个类的reference, 导致空间的浪费
5.有成千上万(打个比方,不止这么多)的对象要反序列化, 而java序列化机制不能复用对象, java反序列化的时候, 每次要构造出新的对象. 在hadoop的序列化机制中, 反序列化的对象是可以复用的.
在这里插入图片描述

五、开源的序列化框架
Google: google protobuffer
Apache: AVRO
facebook: thrift

zookeeper的应用场景


统一命名服务(Name Service)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值