一文入门 Zookeeper
文章目录
- 1. zookeeper 简介
- 1.1 什么是zookeeper
- 1.2 zookeeper 发展历史
- 1.3 zookeeper 典型应用场景
- 1.4 zookeeper 提供的服务
- 1.5 zookeeper的数据模型
- 1.6 znode的分类
- 2. Zookeeper架构
- 2.1 整体架构
- 2.2 session
- 2.3 Quorum 模式
- 2.4 数据一致性
- 3. zookeeper的案例演示
- 3.1 zookeeper 安装
- 3.2 zookeeper启动
- 3.3 zookeeper Client 交互式命令
- 3.4 zookeeper 实现简单的分布式锁
- 3.5 zookeeper实现master-worker架构
- 3.6 zookeeper quorum集群模式
- 4. 总结
通过本篇文章,你能够了解zookeeper的基本知识和应用场景,并且能够通过命令行完整体会到zookeeper的功能和基本应用场景。当然,因为作者水平有限,对分布式系统的理解多少有一些不足,希望大家不吝赐教。
本文通过如下几个方面介绍zookeeper基础:
- zookeeper 的 发展历史 ,提供什么服务 以及 基本功能和应用场景
- zookeeper 的整体架构
- zookeeper 实现简单分布式锁 和 master-work架构,并演示zookeeper的集群模式
1. zookeeper 简介
希望通过zookeeper的发展历史,基本功能介绍以及应用场景来让大家对zookeeper有一个宏观的认识。
1.1 什么是zookeeper
一句话:zookeeper 是一个开源的分布式协同服务系统。说到系统而不是像raft那样的库,我们就能够理解 zookeeper拥有自己的client和server服务进程。
zookeeper的设计目标: 是将那一些复杂且容易出错的分布式系统服务封装起来,抽象出一个高效易用的原语集,并向用户提供简单的接口。
而比较有趣的是zookeeper 这个名字,认为zookeeper的工作性质就像是一个动物园管理员,用来协调整个动物园内的工作,让每一个动物都井井有条得处在自己的笼子里,游客(IO请求)能够安全得在动物园里游览并达到自己想去的位置而不受其他动物的影响。
1.2 zookeeper 发展历史
Zookeeper最早起源于雅虎研究院的一个研究小组。当时研究人员发现,在雅虎内部很多大型系统都依赖一个类似的系统来进行分布式协同,但是这一些系统都存在分布式单点问题
所以雅虎人员开发了一个通用的无单点问题的分布式协调框架,这就是ZK。在 zookeeper 被大量使用之后出现了如下著名的开源项目:
- Hadoop: 使用zookeeper 做namespace的高可用
- HBase: 保证集群只有一个Master;保存hbase:meta 表的位置,保存集群中的RegionServer列表
- Kafka: 集群成员管理,controller 节点选举
可见zookeeper还是能够提供足够的应用场景,且能够得到较多的开源项目的认可。
接下来可以看看zookeeper的典型场景:
1.3 zookeeper 典型应用场景
- 配置管理(configuration management)
- DNS 服务
- 组成成员管理(group membership) – 经典的分布式数据库HBASE
- 各种分布式锁(上一家公司参与的超融合存储项目 中即使用zookeeper来做一些集群锁的作用)
关于组成成员管理 和 分布式锁 后续的介绍中会为大家演示zookeeper原生接口如何实现简单的分布式锁的功能。当然,更深层次实现介绍还需要再摸索一番。
ps: zookeeper 适用于存储和协同相关的关键数据,不适合用于大量数据 存储。
1.4 zookeeper 提供的服务
这里简单说一下 zookeeper 提供什么样子的服务给到客户端。
- Application 直接使用Zookeeper客户端库即可,目前主要是Java接口
- Zookeeper的客户端库负责和Zookeeper集群中的server进行交互
1.5 zookeeper的数据模型
这里描述的并不是zookeeper的架构,仅仅是其数据存储相关的介绍。
我们知道在整个分布式系统的领域里,主流的两种数据存储方式是:树型 和 key-value型。
zookeeper这里选择树型模型(**data-tree)**的考虑是:
- 便于表达数据之间的层次关系
- 便于为不同的应用分配独立的命名空间
如上图中 每一个节点叫做znode,都可以用来保存数据。
同时每一个节点都有一个版本,这个版本是从0开始计数。
关于Zookeeper 提供的data-tree 数据模型有以下几点需要注意:
- 使用Unix 风格路径定位znode,例如 /A/A_1 表示A的子节点A_1
- 支持全量写入和读取,没有像普通文件系统那样支持部分写入和读取
- Data tree的所有API 都是wait-free的;正在调用的API不影响其他API的完成 即为wait-free
- Data tree 直接提供锁这样的分布式系统机制,但可以通过API来实现分布式协同机制
1.6 znode的分类
- 持久性Znode(Persistent):创建之后即使发生节点异常或集群宕机,znode 的信息也不会丢失
- 临时性Znode(Ephemeral): 节点宕机 或 在指定时间timeout 没有给zookeeper集群发消息, 这样的znode就会消失
- 持久顺序性Znode(Persistent_Sequential) znode 关联一个唯一的单调递增整数,这个整数是znode名字后缀,具备持久性。
- 临时顺序性Znode(Ephemeral_Sequential) 拥有顺序性的临时Znode 节点。
2. Zookeeper架构
以下的zookeeper架构仅仅是简要的介绍,并没有深入到各个机制的细节,后续文章会尝试进行探讨。
2.1 整体架构
应用使用zookeeper客户端(shell) 或者 zookeeper客户端库(java api) 使用zookeeper的基本服务。
zookeeper 客户端用来zookeeper集群进行交互。
实际的zookeeper集群可以有两种模式:standalone 模式 和 quorum 模式
- standalone模式 即集群中只有一个节点作为server,一般的分布式系统不需要这样的模式,存在单点问题。适用于开发场景。
- quorum 模式 即 集群有3个及以上的节点,通过quorum协议 为集群维护一个法定人数,只要集群存活的节点大于2/n+1(n表示节点数)个,则集群能够一直对外提供服务。
2.2 session
zookeeper 客户端和zookeeper集群建立链接时,会和集群中的某一个节点创建session。
关闭session有两种情况(客户端和集群断开链接):
- 客户端可以主动关闭session
- zookeeper集群节点没有在指定的timeout时间内收到客户端的消息的话,zookeeper节点也会关闭session。
如果zookeeper客户端库发现链接的zookeeper集群出错,会自动的和其他的zookeeper节点建立链接。如下图:
2.3 Quorum 模式
处于Quorum模式的集群包含多个节点,下图中的三个节点组成了一个zookeeper集群,其中绿色节点1的是leader节点,节点2和节点3是follower节点。leader节点可以处理读写请求,follower节点只能处理读请求,当写请求到达follower节点时会将写请求转发到leader节点。
写请求写入到leader之后,再由leader负责将数据同步到其他的follower节点。
2.4 数据一致性
我们知道分布式系统中的数据一致性主要是由于写 的顺序问题带来的一系列读/写相关的一致性问题。
zookeeper的设计目标是提供协调服务,并不会提供大量的数据存储,所以zookeeper 的主从架构则能够保证写请求的顺序性。
全局可线性化(Linearizable)写入: 大体的意思就是先到达leader的请求会被优先处理,leader决定写请求的执行顺序。
客户端FIFO顺序:来自给定客户端的请求按照发送顺序执行即可。
后续同样会通过 实际集群演示来 展示整个quorum 的zookeeper集群工作形态。
3. zookeeper的案例演示
以下将通过zookeeper的客户端 命令来演示zookeeper 的一些应用场景 以及 集群模式下的quorum机制。
3.1 zookeeper 安装
- zookeeper的环境依赖是JDK7+
- zookeeper源码包下载,我这里使用的是git:
git clone https://github.com/apache/zookeeper.git
git checkout branch-3.5.8
目前最新版本是3.6 - 创建zoo.cfg
可以直接拷贝cp zookeeper/conf/zoo_example.cfg zookeeper/conf/zoo.cfg
主要配置如下两个配置,# the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=/tmp/zookeeper # the port at which the clients will connect clientPort=2181 ...
- 导入
zookeeper/bin
目录到环境变量,方便使用相关的cli脚本,我放到了自己的~/.zshrc
下,其他人可以放在自己的~/.bashrc
这样能够在整个客户端的不同位置运行zookeeper的客户端脚本命令。export ZOOKEEPER_HOME="$HOME/IdeaProjects/zookeeper" export PATH="$ZOOKEEPER_HOME/bin/":$PATH
到此 整个zookeeper 已经安装完毕,当然这里还需要描述以下不同操作系统下的方式,以上步骤适用于所有类unix系统,包括mac os;Windows下只有最后一步不同,记得windows的shell rc文件和unix不同。
3.2 zookeeper启动
以下可以直接运行的命令是我之前已经将zookeeper/bin 目录放入到了path变量中,所以能够直接运行,具体步骤在上一节。
启动server
zkServer.sh start
/usr/bin/java ZooKeeper JMX enabled by default Using config: /Users/zhanghuigui/IdeaProjects/zookeeper/bin/../conf/zoo.cfg Starting zookeeper ... STARTED
可以在你自己的zookeeper的安装目录下有一个
logs
文件目录,用来保存服务进行运行的相关日志
~/IdeaProjects/zookeeper/logs
,其中IdeaProjects
是我自己的目录,可以打开你自己的目录即可。
可以看到日志中并没有异常报错。我们再去zookeeper的data目录看有哪一些数据:
╰─$ tree . ├── version-2 │ └── snapshot.0 # zookeeper的快照文件 └── zookeeper_server.pid #zookeeper server的进程id1 directory, 2 files
启动 client
zkCli.sh
,能够看到已经运行的client,因为我们没有变更zoo.cfg端口号,所以client也会默认访问zoo.cfg的端口号建立连接。... 2020-11-21 14:56:40,635 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/[0:0:0:0:0:0:0:1]:2181, sessionid = 0x100016e76ff0000, negotiated timeout = 30000WATCHER::WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2181(CONNECTED) 0]
这个时候能够进行交互命令,实现zookeeper的client和server的通信。
3.3 zookeeper Client 交互式命令
- 输入
h
可以看到很多交互式命令[zk: localhost:2181(CONNECTED) 0] h ZooKeeper -server host:port cmd argsaddauth scheme authcloseconfig [-c] [-w] [-s]connect host:portcreate [-s] [-e] [-c] [-t ttl] path [data] [acl]delete [-v version] pathdeleteall pathdelquota [-n|-b] pathget [-s] [-w] pathgetAcl [-s] path...
- 输入
ls -R /
所有访问znode的命令都需要加绝对路径,可以看到已经有一些根节点下的子节点存在了[zk: localhost:2181(CONNECTED) 2] ls -R / / /zookeeper /zookeeper/config /zookeeper/quota
create /app
创建第几个永久 znode
再次查看对应的znode data tree信息[zk: localhost:2181(CONNECTED) 26] create /app1 Created /app1 [zk: localhost:2181(CONNECTED) 27] create /app2 Created /app2 [zk: localhost:2181(CONNECTED) 28] create /app1/app1_1 Created /app1/app1_1 [zk: localhost:2181(CONNECTED) 29] create /app1/app1_2 Created /app1/app1_2
[zk: localhost:2181(CONNECTED) 30] ls -R / / /app1 /app2 /zookeeper /app1/app1_1 /app1/app1_2 /zookeeper/config /zookeeper/quota
stat /
查看 根目录 znode元信息[zk: localhost:2181(CONNECTED) 31] stat / cZxid = 0x0 ctime = Thu Jan 01 08:00:00 CST 1970 # 创建时间 mZxid = 0x0 mtime = Thu Jan 01 08:00:00 CST 1970 #修改时间 pZxid = 0x13 cversion = 17 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 3 #子节点数量
3.4 zookeeper 实现简单的分布式锁
分布式锁的基本要求如下:
- 锁被持有时其他 client无法访问 临界区的资源
- 持有锁的进程/节点 宕机 ,锁需要被释放(防止死锁)
这是分布式锁的基本功能,通过zookeeper 显示如上基本功能:
使用两个Client来模拟一个集群中的两个节点,访问锁的情况。
基本步骤如下:
- 节点一 持有锁 – 成功
- 节点二 尝试持有锁 – 失败
- 节点二 监控锁的使用情况
- 节点一 异常退出,并释放锁
- 节点二 感知到锁被释放,从而持有锁 – 成功
如下演示:
这里主要通过zookeeper的临时节点(Ephemeral) 来实现的,因为临时znode节点异常退出或者client和server无心跳,则znode数据会被清除掉,能够作为分布式锁的节点异常退出锁释放的条件。
不过这样的实现 后续需要深入探索以下zookeeper的一致性 和 这种场景下的性能问题,如果成百上千的客户端在等待这把锁,能否足够快得释放 以及 如果保证每次只有一个客户端拿到锁(如何保证多个客户端同时创建一个inode,而只能有一个客户端创建成功。。。,需要深入探讨一下zookeeper的一致性模型)。
3.5 zookeeper实现master-worker架构
master-worker 架构是一种应用比较广泛的分布式系统架构。
其中有一个master负责监控worker的状态,并负责为worker分配对应的任务。
有如下几个约束规则:
- 在任何时刻,系统中只有一个master,不能同时出现两个mater或者多个master,这样整个系统的调度就乱掉了。
- 系统中除了处于active状态的master,还有一个backup状态的mater,如果active master异常,则backup master能够立即接管,进行任务分配
- master 实施监控worker状态,并能及时收到worker成员变化的通知。master收到worker成员变化的时候通常会重新进行任务分配。
比如HBase:
HMBase 是系统中的Master,HRegionServer 是系统中的worker。
HMBase 实时监控HBase Cluster中worker的变化,把Region分配给各个HRegionServer。系统中有一个HMBase 服务处于active,其他处于backup状态。
比如CEPH中的Cephfs:
同样多个mds提供cephfs元数据管理功能,每一时刻只有一个mds-active ,所有的元数据调度都由这个active的mds负责,其他备mds则提供active mds的接管服务。
那么如何在Zookeeper中实现master-worker架构呢?
使用一个临时节点 /master表示master。master想要行使职能之前先要创建这个znode,创建成功,则进入active状态,否则进入
backup
状态,并使用watch机制监控/master,来及时得跟踪active master的状态。加入系统中现在有一个active master, 一个 backup master。如果active master异常,则它创建的/master就会被删除,并且被处于监听状态的backup master watch到,此时backup master通过创建自己的/master 临时节点来成为active master行使职能。
worker 通过在/workers 目录下创建子节点来加入集群
处于active 状态的master 会通过watch 机制监听/works 下的znode列表,来感知集群worker的变化。
使用zookeeper实现 的基本功能master-worker架构 以及 data tree中对应的znode分布如上图,master通过一个znode节点表示,work则分布在一个大的workers父节点之下。
其中zookeeper master 和 backup master选举的演示功能如下:
主要是通过stat -w /master
监控状态变化
zookeeper master监控 works成员列表变化的演示过程如下:
主要通过ls -w /works
监控节点成员变化
3.6 zookeeper quorum集群模式
之前的简单分布式锁以及master-work架构都是在同一台机器上通过不同的客户端实现的,接下来的集群模式如果大家想要了解且有多台服务器,玩一玩也不错。没有多台服务器也是可以的,按照如下配置即启动多个server进程组成quorum。
配置文件
之前单个server 只需要一个zoo.cfg,那我们配置集群模式肯定需要多个不同的zoo.cfg
其中的dataDir
和clientPort
需要配置成不同的值,三个zoo.cfg中的server.n
需要配置成一样的。server.1=127.0.0.1:7777:7778 server.2=127.0.0.1:6666:6667 server.3=127.0.0.1:5555:5556
其中server.n中的ip是当前节点的ip,如果大家有各自的服务器,直接设置成服务器可通信的ip地址即可。
ip之后的第一个端口号是:quorum 协议的通信端口,第二个端口号是leader选举的端口号
如下配置
除此之外,启动server之前,还需要先在每个server各自的dataDir目录下创建一个名称为myid
的文件,内存分别是1
,2
,3
,即在server.1的dataDir目录下创建一个myid文件,内容为1。其他的server依次都需要创建。启动过程需要通过前台启动server进程,并指定对应的zoo.cfg
zkServer.sh start-foreground ./conf/zoo-node1.cfg
,这样日志能够打印到客户端启动第一个server的时候,会有一些报错,因为只有一个节点,quorum无法满足法定人数。
依次启动第二个server和第三个server,即能够发现对应的选举过程,启动第二个server的时候两个server中会有一个成为leader,此时启动client,即能够正常提供zookeepe服务。通过命令
zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
,指定对应的三个server ip和port即能够建立client和zookeeper集群的链接。
演示过程如下:
4. 总结
通过对zookeeper的简介,zookeeper的基本架构,zookeeper的一些简单应用的介绍,我们对zookeeper有了全面却很初步的理解,更多的细节:zookeeper 如何实现服务发现,zookeeper如何做到事件驱动,zookeeper的类似quorum模式zab协议的实现,以及如何在生产环境中通过java代码实现分布式锁,分布式队列,选举 这一系列更加底层更加易用的实现将在后续的学习中不断总结。
这是一个非常有代表性的分布式系统,涉及 分布式通信,分布式协议,分布式存储 ,复杂度相比于专门的分布式存储 系统低很多,更棒的是开源。每一个精妙的设计我们都能够看到其底层实现,细细品味。
相关文章:

龙岩学院和三明学院计算机专业,龙岩学院和三明学院哪个比较好?
满意答案lxq051052014.06.27采纳率:51% 等级:7已帮助:459人520的分数算不错了,在择校中可以采取“冲、稳、保、垫”的志愿填报方法,冲的话可以选择漳师、闽江和厦门理工学院,都是不错的选择,…

MySQL 的 find_in_set函数使用方法
很多时候我们在设计数据库时有这种情况,比如: 有个文章表里面有个type字段,他存储的是文章类型,有 1头条,2推荐,3热点,4图文 .....11,12,13等等 现在有篇文章他既是 头条,又是热点,还是图文,type中以 1,3,4的格式存储. 那们我们如何用sql查找所有type中有4图文标准的文章呢,这就…

SCCM符合性设置
符合性设置--可以针对注册表值、脚本、文件系统、补丁更新情况进行符合性检查,除了在报表中查看结果外,还可以在CCM客户端 的 配置 中查看符合性评估结果,适合排错1.配置项目---新建针对 注册表值、脚本、文件系统等的符合性检查规则 …

Java(三):序列化
1、什么是Java对象序列化? Java的对象序列化是将那些实现了Serializable接口的对象转化成一个字节序列,并能够在以后将这些字节序列完全恢复成原来的对象。简单来说序列化就是将对象转化成字节流,反序列化就是将字节流转化成对象。 对象必须在…

Go 分布式学习利器(11)-- Go语言通过单链表 实现队列
一个小实验,将之前学习的Go相关的语法做个总结。 包括: Go语言接口特性Go语言封装特性Go语言 变量,指针,函数 语法GO语言 条件和循环语句 的语法GO语言的测试程序 通过链表实现一个队列,元素在其中 拥有先进先出的特…
最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr...
问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X“x0,x1,…,xm-1”,序列Y“…

逆战服务器在哪个文件夹,逆战的背景音乐文件夹放在哪?别说在服务器上面!...
满意答案Dim185629442017.01.11采纳率:58% 等级:13已帮助:7224人你右键逆战图标,有个打开文件位置,点开,找就可以了。。 追问: 如果我把我喜欢的音乐文件放进去,我喜欢的音乐会成…

ruby调用java代码
为什么80%的码农都做不了架构师?>>> ruby使用rjb调用java代码 require rjb#加载jar包 Rjb::load(classpath /home/deployer/DmCodec.jar, jvmargs[]) #new一个对象 DmCodec Rjb::import(com.zapya.DmCodec).new #调用实例方法 tmp DmCodec.encodeB6…

VMware虚拟机安装黑苹果MacOS Mojave系统详细教程
更多资源请百度搜索:前端资源网 欢迎关注我的博客:www.w3h5.com 最近遇到一个H5页面的 iPhone X 刘海兼容问题。查到一个 XCode 编辑器,可以模拟 iPhone X 环境运行。 然后发现,XCode 是专门为苹果的 MacOS 系统设计的一款开发工具…

LSM 优化系列(四) -- Rocksdb和Lethe 对Delete问题的优化
文章目录前言1. 问题背景2. 问题复现3. Rocksdb 的 Delete-Aware 优化3.1 可配置的 Delete-Aware调度3.2 Compaction 逻辑对 delete key的优化4. Lethe: A Tunable Delete-Aware LSM Engine . SIGMOD20前言 本文介绍过程中涉及到的源代码是基于rocksdb 6.4.6 版本的。 同时需…

CodeForces Round #287 Div.2
A. Amr and Music (贪心) 水题,没能秒切,略尴尬。 1 #include <cstdio>2 #include <algorithm>3 using namespace std;4 5 const int maxn 100 10;6 int a[maxn], r[maxn], ans[maxn];7 8 int cmp(int i, int j) { return a[i] < a[j]; …

什么叫安装文件索引服务器,搜出精彩 玩转Windows 2008系统心得
【IT168 专稿】不少朋友已经在不经意间与Windows Server 2008系统进行了亲密接触,在一段时间的接触之后,不知大家对该系统的文件搜索功能会有什么样的体会?其实,Windows Server 2008系统的文件搜索功能与以往相比有了很大进步&…

取eclipse console 打印字符串,判断日志是否有异常
2019独角兽企业重金招聘Python工程师标准>>> 1. 取得当前输入的console /*** 取得控制台的字符串的Docment* param processConsoleName 控制台名称,如在java application 中定义的名字为test ,则这个地方的输入为test即可* return null*/public stati…

PAT乙级1028
1028 人口普查 (20 分)某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是…

Go 分布式学习利器(12)-- Go语言的扩展和复用
Go语言无法天然支持继承,但是又想要实现面向对象的特性。 即父类对象 使用子类对象初始化,那么该父类对象调用的函数就是子类实现的函数 ,从而满足LSP(子类交换原则)。 案例一: Go语言 支持扩展父类的功能…

displaytag 导出
只使用displaytag的导出功能,表单展示用jqgrid实现。只需要后台修改一部分代码,其他的表单都能使用这个功能导出。导出四种文件格式:csv,excel,xml,pdf。 思路:在过滤器中处理,过滤器…

两个下拉框相关联ajax,触发第二个下拉框以显示基于从第一个下拉框中选择的值的值ajax...
我有两个引导程序下拉框。当我们点击另一个下拉菜单时,其中一个会根据用户选择的国家显示来自数据库的所有国家名称,另一个下拉菜单应该选择状态。 当我点击一个下拉菜单时,我做了一个ajax请求来显示国家名称。如何根据国家选择触发其他下拉菜…

使用apache服务器配置虚拟目录
安装好了apachephpmysql之后就像在自己电脑上安装wordpress玩玩,因为安装好之后根目录在D盘, 所以就想自己配置一个虚拟目录指向路径为D:\wordpress的wordpress 在httpd.conf中添加虚拟目录之后去访问localhost:88/myblog却出现了403错误,提示…

YARN的HA
拓展:线程与进程的区别 进程是由一个以上的的线程组成的 ps -ef 能出现的就是进程。 YARN HA hadoop001:zk rm(zkfc) nmhadoop002:zk rm(zkfc) nmhadoop003:zk nm ZKFC: 线程 只作为RM进程的一个线程而非独立的进程存在 RMStateSt…

一个复杂的存储过程
首先说明一下我这个存储过程的功能: 根据不同的查询条件组合进行查询数据,数据库中有项目信息表Project 有项目区域表ProjectArea 项目信息表Project和项目区域表的关联是通过ProjectArea和AreaID进行一对一关联,项目区域信息中的信息有所属关…

Go 分布式学习利器(13)-- Go语言的多态
文章目录1. 基本的多态实现2. 空接口与断言3. Go接口的最佳实践1. 基本的多态实现 我们知道C中实现多态是通过虚函数表 和 继承来 实现的。 类似如下代码: class Programmar{ public:virtual void write_hello_world() 0; }class GoProgrammar: public Programma…

服务器搭建虚拟win云服务,云服务器创建win10虚拟机
云服务器创建win10虚拟机 内容精选换一换弹性云服务器(Elastic Cloud Server,以下简称ECS)是由CPU、内存、镜像、云硬盘组成的一种可随时获取、弹性可扩展的计算服务器,同时它结合VPC、虚拟防火墙、数据多副本保存等能力,为您打造一个高效、可…

预编译 ASP.NET 网站以进行部署
预编译 ASP.NET 网站以进行部署和更新 打开一个命令窗口并定位到包含 .NET Framework 的文件夹。 .NET Framework 将安装在以下位置。 %windir%\Microsoft.NET\Framework\version运行 aspnet_compiler 命令,在命令提示符下键入以下内容,同时指定源&…

Go 分布式学习利器(14)-- Go语言的错误处理
1. Go 的错误机制 Go 语言的错误机制中与其他语言的主要差异如下: 没有异常机制error 类型实现了 error接口type error interface {Error() string }可以通过errors.New来快速创建错误实例errors.New(" num is not in range[0,100]")如下测试代码演示基…

30 个 php 操作 redis 常用方法代码例子
这篇文章主要介绍了 30 个 php 操作 redis 常用方法代码例子 , 本文其实不止 30 个方法 , 可以操作 string 类型、 list 类型和 set 类型的数据 , 需要的朋友可以参考下redis 的操作很多的,以前看到一个比较全的博客,但是现在找不到了。查个东西搜半天,下面整理一下php 处理 re…

电脑机时,电脑死机时,为啥会忍不住扇它一巴掌?
我们为什么会把自己的愤怒发泄在机器人呢?对于人们为何会打机器这个问题,国外媒体Hopes&Fears请教了很多专家,包括精神治疗医师、机械工程师、愤怒管理专家以及流行文化专家。有一场非常重要的会议就要召开了,你必须在五分钟时…

Android所有系统版本USB调试模式打开方法
参考 Android所有系统版本USB调试模式打开方法

docker(4)docker的网络,自定义网桥
Docker 的网络 运行 ifconfig 找到 docker0 : 虚拟网卡默认网卡名称为docker0 查看docker 的网桥: 我这里默认们没有进行安装 网桥管理设备:进行安装一下; yum install bridge-utils 命令:查看网桥crctl show: 注意上图中的i…

Go 分布式学习利器(15) -- Go 实现 深搜和广搜
强化语法,回顾算法。 通过Go语言实现 深度优先搜索 和 广度优先搜索,来查找社交网络中的三度好友关系(三度指的是一个节点到 其相邻节点 到 其相邻节点的节点 ,图递增三层好友关系)。 涉及到的Go语言语法:…

css背景属性
CSS背景: 属性 描述 background 简写属性,作用是将背景属性设置在一个声明中。 background-attachment 背景图像是否固定或者随着页面的其余部分滚动。 background-color 设置元素的背景颜色。 background-image 把图像设置为背景。 backgroun…