🍳作者:天海奈奈
💭眼过千遍不如手锤一遍:推荐一款模拟面试,斩获大厂 o f f e r ,程序员的必备刷题平台 − − 牛客网
👉🏻点击开始刷题之旅
目录
Access Control List权限控制列表粒度细: 5种权限.
CREATE :可以创建一个子节点READ :可以从节点获取数据并列出其子节点WRITE :可以为节点设置数据
解决单点时的问题,创建无单点问题的分布式协调框架,精力集中在处理业务逻辑。
名称就是Zookeeper动物园管理员,由于当时雅虎很多项目都以动物来命名,可以说是相当贴切了。作用就是协调大家让大家步伐一致。诞生了Zookeeper用来做分布式协调。
1 单点系统是不可靠的,外界不可控因素过多,发生故障我们不容易提供稳定服务。
2 Zookeeper具有高可用性且对外提供数据一致。
官网 : Apache ZooKeeper

Zookeeper提供分布式应用程序的分布式协调服务。服务的对象是分布式的应用城西,自身也是分布式的,它的主要作用是协调服务。简单理解为可靠的对外提供一致服务的数据库
不会因为某一个节点的宕机而不可用。
1,同一个客户端发送请求生效是有顺序的。
2,对Zookeeper集群操作时保证在所有集群中的操作是一致的,不会出现有的成功有的不成功。
3,不管连接到那个Zookeeper服务器,提供的数据都是一致的。
4,一旦生效能保证任务会一直保留。
5,同步速度块

服务连接到leader,协调不同的server进行工作,五个server下面的client链接的时候也把压力进行了分散,不同的客户端链接的是不同的服务器,一个服务器对外提供的能力是有限的,不同于点服务器的模式,他提高了服务器的能力并保证数据是一致的。
Leader server会把写相关的请求处理掉,同步到其他上面去。
与单机锁的差别不大,只是部署在分布式上面的,应用的是他节点的唯一性。
应用到舰监听的能力也就是Wacher
dubbo就能用Zookeeper来保存与服务变化相关的信息
先登录到虚拟机,这里用的是Xshell 直接虚拟机里终端操作也差不多
这里以3.6.3为例,点击进去


我们下载第一个最大的,右键复制链接回到命令台
输入:wget 把复制的链接右键粘贴上去 回车

等待下载完成,虽说不快但也能接受,三分钟刚好看看下面该怎么做

解压:
下载完成后进行解压缩 输入 tar zxvf 把上面提供的 apache-zookeeper-3.6.3-bin.tar.gz复制下来,回车。

解压缩完成后,输入ls

看到这个解压的文件夹已经存在了
我们现在进入这个文件夹

输入cp conf/zoo_sample.cfg conf/zoo.cfg
复制完成后打开zoo.cfg,先输入cd conf 进入到conf 再输入vim zoo.cfg

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# 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
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true
ticktime: 时间单元,比如我们设置超时时间是设置几个时间单元这里就是一个单元有多久
clientPort=2181 : 这就是对外提供的端口号,默认就是2181
没啥改的,看一眼记一下这配置文件就好。esc + : +q 退出即可
输入 cd.. 返回上级目录
输入./bin/zkServer.sh start 如果想关闭,输入./bin/zkServer.sh stop 到此lunix下的安装与调整配置文件以及如何启动就讲完了。linux下想要启动的话需要有java环境。

其实操作都是一样的,不同的是windows下启动我们执行的是bin下的zkServer.cmd
这个文件

zookeeper的基本数据类型的结构是树形结构
可以存储数据,但是数据要尽量的简洁
是树形结构,有父子节点之分
有版本号的概念,可以用来防止误操作
可以在节点上防止监听器去感知节点的变化
持久节点 如果在创建之初我们将它设置为持久节点,就算我们断网了这个节点也是存在的
临时节点 如果客户端断了,过一段时间节点就会被清理掉。
顺序节点 如果使用了顺序这个特性zookeeper会在这个节点后面加10位的数字 相当于计数器
eg:0000000001 0000000002,且可以保证同一个父节点下这个顺序是唯一的 既可以应用在持久节点也可以应用在临时节点。
如果只是一次性的操作就选择临时节点
如果想长久地保存一些信息就使用
输入cd apache-zookeeper-3.6.3-bin 回车后输入./bin/zkServer.sh start
看到启动成功后输入: ./bin/zkCli.sh -server 127.0.0.1:2181

末行出现SyncConnected证明我们连接成功

create [-s] [-e] [-c] [-t ttl] path [data] [acl] 带括号的是可选参数,可加可不加 path是必须假的代表节点路劲
delete [-v version] path : version 是版本号,只有符合这个版本的才会被删除,不然会删除失败
get [-s] [-w] path :获取查询
set [-s] [-v version] path data :修改
我们先看一下原始的目录结构,可以看到根目录下只有zookeeper 文件夹 他有两个子文件夹 config, quota 这是系统默认生成的。

结构
现在我们试一下创建两个结点 并给结点附值
输入
create /java1 hellojava1
create /java1/zk1 hellozk1
create /java2 hwllojava2
create /java2/zk2 hellozk2
再以递归的方式 看看目录中都有哪些文件 输入 ls -R /

我们创建在子目录中创建两个节点,两个节点还有自己的子节点
使用get来查看节点的数据 输入 get /java1

现在来演示set 的用法
我们把java2/zk2 的hellozk2改为hellochange
是用delete来删除节点,删除节点是要保证删除节点下没有其他节点 演示删除java2

可以看到java2这个节点就被删除了

新建一个节点java3 看到内部版本数据dataVersion=1 此1非彼1
这时候假设有两个客户端想要改变这个节点的数据。

第一个人根据当前节点版本把值进行了修改,修改后版本发生了变化
此时第二个客户端如果还想通过版本号1来进行修改就不会成功

这就是乐观锁的思想,与版本好相关的操作不仅仅有set。
我们看java3 节点的属性 ephemeralOwner = 0x0 这个代表持久节点。服务退出重进它是会一直存在的。
那么临时节点如何创建呢 输入 :create /java4 -e

ephemeralOwner = 0x100017c19940000 这就代表它是临时节点 如果退出后重连,过一段时间这个节点就会被清除。
输入: create /java5 create /java5/abc -s
新建在父节点下面的子节点后面会有10位的数字 保证数据的唯一性。-s 建立的节点也是持久节点,-s 与 -e 是可以一起使用的。
类似于监视器、触发器、监督者
使用场景:通知,例如配置中心更新数据
NodeCreated节点创建
NodeDeleted节点删除
NodeDataChanged节点数据修改
NodeChildrenChanged子节点变更
打开idea 创建一个maven工程
名字随便取一个就叫zk-test吧,组件一改

我们要使用zookeeper那我们就引入依赖
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
</dependencies>
首先来测试下连接和断开
/**
* 连接到zk
*/
public class FirstConnect {
public static void main(String[] args) throws IOException, InterruptedException {
ConnectWatcher connectWatcher = new ConnectWatcher();
//第一步指定zookeeper的属性,
ZooKeeper zooKeeper = new ZooKeeper(zkConstant.ZK_HOST, zkConstant.CONNECT_TIMEOUT, connectWatcher);
System.out.println("客户顿开始连接zk服务器");
States states = zooKeeper.getState();
System.out.println(states);
System.out.println("11111");
Thread.sleep(2000);
System.out.println(states);
Thread.sleep(2000);
zooKeeper.close();
}
}
ZooKeeper()第一个参数是地址 第二个参数是连接
的超时时间,第三个参数是监听器。
常量类:
public class zkConstant {
public static final String ZK_HOST = "127.0.0.1:2181";//本机地址
public static final Integer CONNECT_TIMEOUT = 8000;//超时时间
}
watcher 监听类
/**
* 连接Watcher
*/
public class ConnectWatcher implements Watcher {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("ConnectWatcher被调用");
//根据state去判断
if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
if (watchedEvent.getState() == Event.KeeperState.Closed){
System.out.println("连接断开");
}
}
}

由于连接是有延迟的我们一起动先打印一次状态,延迟两秒在打印一次状态,延迟两秒退出。连接和退出时监听器会打印连接和断开。
运行结果:

实现节点的增删改查
/**
* 描述: 对节点的增删改查
*/
public class ZkCRUD {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ConnectWatcher connectWatcher = new ConnectWatcher();
//第一步指定zookeeper的属性,
ZooKeeper zooKeeper = new ZooKeeper(zkConstant.ZK_HOST, zkConstant.CONNECT_TIMEOUT, connectWatcher);
System.out.println("客户顿开始连接zk服务器");
States states = zooKeeper.getState();
System.out.println(states);
Thread.sleep(2000);
System.out.println(states);
//对节点进行增删改查
//第一个参数是地址,第二个参数是byte数组,第三个参数是acl 我们选择对所有都开放,第四个参数是节点类型 这里选择临时节点
zooKeeper.create(zkConstant.PATH_1,"firstOne".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
Thread.sleep(2000);
//由于数据时byte数组
byte[] bytes = null;
bytes = zooKeeper.getData(zkConstant.PATH_1,null,null);
System.out.println(new String((bytes)));
Thread.sleep(2000);
//改
zooKeeper.setData(zkConstant.PATH_1,"secondOne".getBytes(),-1);//-1是任意版本都可以
Thread.sleep(2000);
bytes = zooKeeper.getData(zkConstant.PATH_1,null,null);
System.out.println(new String(bytes));
//删
zooKeeper.delete(zkConstant.PATH_1,-1);
Thread.sleep(2000);
zooKeeper.close();
}
}

我们在改,删时第二个参数watcher用的是null,如果我们要使用监听且有我们自定义的监听就用true。
原生客户端操作起来略显复杂,不支持重连重试
引入依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
/**
* 描述: 用Curator来操作ZK
*/
public class CuratorTests {
public static void main(String[] args) throws Exception {
String connectString = "127.0.0.1:2181";
String path = "/curator1";//节点路径
//重试机制
ExponentialBackoffRetry retry = new ExponentialBackoffRetry(1000, 10);
//新建客户端
CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retry);
client.start();
//监听
client.getCuratorListenable().addListener((CuratorFramework c, CuratorEvent event) -> {
switch (event.getType()) {
case WATCHED:
WatchedEvent watchedEvent = event.getWatchedEvent();
if (watchedEvent.getType() == EventType.NodeDataChanged) {
System.out.println(new String(c.getData().forPath(path)));
System.out.println("触发节点更改事件");
}
}
});
String data = "test";
String data2 = "test2";
//增
client.create().withMode(CreateMode.EPHEMERAL).forPath(path, data.getBytes());
//查
byte[] bytes = client.getData().watched().forPath(path);
System.out.println(new String(bytes));
//改
client.setData().forPath(path, data2.getBytes());//watched是一次性监听事件,重复调用也不会触发
client.setData().forPath(path, data2.getBytes());//watched是一次性监听事件,重复调用也不会触发
client.setData().forPath(path, data2.getBytes());//watched是一次性监听事件,重复调用也不会触发
Thread.sleep(2000);
client.delete().forPath(path);
Thread.sleep(2000);
//永久监听
String pathNew = "/curatorForEver";
client.create().withMode(CreateMode.EPHEMERAL).forPath(pathNew, data.getBytes());
NodeCache nodeCache = new NodeCache(client, pathNew);
nodeCache.start();
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
ChildData currentData = nodeCache.getCurrentData();
if (currentData != null) {
System.out.println("触发了永久监听的回调,当前值为:" + new String(currentData.getData()));
}
}
});
client.setData().forPath(pathNew, data2.getBytes());
Thread.sleep(2000);
client.setData().forPath(pathNew, data2.getBytes());
Thread.sleep(2000);
client.setData().forPath(pathNew, data2.getBytes());
Thread.sleep(2000);
client.delete().forPath(pathNew);
}
}

没有使用永久监听时是不会进行回掉模式一次性,所以只打印了一次,如果使用永久监听就不一样了。
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
system-view进入系统视图quit退到系统视图sysname交换机命名vlan20创建vlan(进入vlan20)displayvlan显示vlanundovlan20删除vlan20displayvlan20显示vlan里的端口20Interfacee1/0/24进入端口24portlink-typeaccessvlan20把当前端口放入vlan20undoporte1/0/10删除当前VLAN端口10displaycurrent-configuration显示当前配置02配置交换机支持TELNETinterfacevlan1进入VLAN1ipaddress192.168.3.100
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
大家好,我正在尝试设置一个开发环境,并且我一直在关注以下教程:Linktotutorial我做得不是很好,除了最基本的版本控制内容外,我对终端命令没有任何实际经验。我点击了第一个链接并尝试运行source~/.bash_profile我得到了错误;mkdir:/usr/local/rbenv/shims:权限被拒绝mkdir:/usr/local/rbenv/versions:权限被拒绝现在每次我加载终端时都会出现错误。bash_profile的内容;exportPATH=/usr/local/rbenv/bin:$PATHexportRBENV_ROOT=/usr/local/rbe
在我的Character模型中,我添加了:字符.rbbefore_savedoself.profile_picture_url=asset_path('icon.png')end但是,对于数据库中已存在的所有角色,它们的profile_picture_url为nil。因此,我想进入控制台并遍历所有这些并进行设置。在我试过的控制台中:Character.find_eachdo|c|c.profile_picture_url=asset_path('icon.png')end但这给出了错误:NoMethodError:undefinedmethod`asset_path'formain:O
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5