当前位置: 首页 > news >正文

Zookeeper【Curator客户端Java版】从0到1——万字学习笔记

目录

初识Zookeeper

Zookeeper作用

维护配置信息

分布式锁服务

集群管理

生产分布式唯一ID

Zookeeper的设计目标

Zookeeper 工作机制

数据模型

ZooKeeper 命令操作

服务端常用命令

 客户端常用命令

ZooKeeper JavaAPI操作

Curator 介绍

Curator API 常用操作

导入依赖

建立连接

创建节点

查询节点

修改节点

删除节点

Watch事件监听

概念

API演示 

分布式锁实现

分布式锁概述

ZooKeeper分布式锁原理 

​编辑

Curator实现分布式锁

API 

1. 配置

2. 可重入锁InterProcessMutex

3. 不可重入锁InterProcessSemaphoreMutex

4. 可重入读写锁InterProcessReadWriteLock

5. 联锁InterProcessMultiLock

6. 信号量InterProcessSemaphoreV2

7. 共享计数器

7.1. SharedCount

ZooKeeper 集群搭建

选举机制

选举过程

异常情况处理

集群中的角色定位

初识Zookeeper

  Zookeeper是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调存储服务。

  • 维护配置信息

  • 分布式锁服务

  • 集群管理

  • 生成分布式唯一ID

Zookeeper作用

维护配置信息

  java编程经常会遇到配置项,比如数据库的urlschemauserpassword等。通常这些配置项我们会放置在配置文件中,再将配置文件放置在服务器上当需要更改配置项时,需要去服务器上修改对应的配置文件。

        但是随着分布式系统的兴起,由于许多服务都需要使用到该配置文件,因此有必须保证该配置服务的高可用性(highavailability)和各台服务器上配置数据的一致性。

        通常会将配置文件部署在一个集群上,然而一个集群动辄上千台服务器,此时如果再一台台服务器逐个修改配置文件那将是非常繁琐且危险的的操作,因此就需要一种服务能够高效快速且可靠地完成配置项的更改等操作,并能够保证各配置项在每台服务器上的数据一致性。

  zookeeper就可以提供这样一种服务,其使用Zab这种一致性协议来保证一致性。现在有很多开源项目使用zookeeper来维护配置,如在 hbase中,客户端就是连接一个 zookeeper,获得必要的 hbase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列 kafka中,也便用zookeeper来维护 brokers的信息。在 alibaba开源的soa框架dubbo中也广泛的使用zookeeper管理一些配置来实现服务治理。

分布式锁服务

        一个集群是一个分布式系统,由多台服务器组成。为了提高并发度和可靠性,多台服务器上运行着同一种服务。当多个服务在运行时就需要协调各服务的进度,有时候需要保证当某个服务在进行某个操作时,其他的服务都不能进行该操作,即对该操作进行加锁,如果当前机器挂掉后,释放锁并 fail over到其他的机器继续执行该服务

集群管理

        一个集群有时会因为各种软硬件故障或者网络故障,出现棊些服务器挂掉而被移除集群,而某些服务器加入到集群中的情况,zookeeper会将这些服务器加入/移出的情况通知给集群中的其他正常工作的服务器,以及时调整存储和计算等任务的分配和执行等。此外zookeeper还会对故障的服务器做出诊断并尝试修复。

生产分布式唯一ID

        在过去的单库单表型系统中,通常可以使用数据库字段自带的auto_ increment属性来自动为每条记录生成一个唯一的ID。但是分库分表后,就无法在依靠数据库的auto_ Increment属性来唯一标识一条记录了。此时我们就可以用zookeeper在分布式环境下生成全局唯一ID


Zookeeper的设计目标

zooKeeper致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调服务

高性能

  • zookeeper将全量数据存储在内存中,并直接服务于客户端的所有非事务请求,尤其用于以读为主的应用场景

高可用

  • zookeeper一般以集群的方式对外提供服务,一般3~5台机器就可以组成一个可用的 Zookeeper集群了,每台机器都会在内存中维护当前的服务器状态,井且每台机器之间都相互保持着通信。只要集群中超过一半的机器都能够正常工作,那么整个集群就能够正常对外服务

严格顺序访问

  • 对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反应了所有事务操作的先后顺序


Zookeeper 工作机制

  • Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。也就是说 Zookeeper = 文件系统 + 通知机制。


数据模型


ZooKeeper 命令操作

本节主要基于命令行操作Zookeeper

服务端常用命令

 客户端常用命令


ZooKeeper JavaAPI操作

Curator 介绍

Curator API 常用操作

注意:如果你采用的是Zookeeper3.5及以上的版本,需要采用的是Curator4.0版本来作为其客户端,对于Zookeeper3.5以下的版本,Curator4.0也兼容,所以无脑4.0

导入依赖

<!--curator-->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.0.0</version>
</dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.0.0</version>
</dependency>

建立连接

/*** 建立连接*/@Beforepublic void testConnect() {/*** @param connectString       连接字符串。zk server 地址和端口 "192.168.149.135:2181,192.168.149.136:2181"* @param sessionTimeoutMs    会话超时时间 单位ms* @param connectionTimeoutMs 连接超时时间 单位ms* @param retryPolicy         重试策略*//* //重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,10);//1.第一种方式CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.149.135:2181",60 * 1000, 15 * 1000, retryPolicy);*///重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
————————————————————————————————————————————————————————————————————————————————//2.第二种方式//CuratorFrameworkFactory.builder();client = CuratorFrameworkFactory.builder().connectString("192.168.149.135:2181").sessionTimeoutMs(60 * 1000).connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("itheima") // 设置命名空间,后续创建的节点默认以此为根节点.build();//开启连接client.start();}

创建节点

题外小知识点:如果我们在Junit单元测试的时候,一个测试方法的需要调用到其他@Test方法来进行初始化 or 资源释放操作,可以通过@Before @After 注解来标注执行该@Test方法前先执行什么方法,后执行什么方法

@Before
public void connect(){建立连接的逻辑
}@Test
public void consum(){建立连接后执行的逻辑
}@After
public void release(){释放连接逻辑
}

上述代码,运行consum方法后,他的加载顺序是 connect() ——> consum() ——> release() 

   /*** 创建节点:create 持久 临时 顺序 数据* 1. 基本创建 :create().forPath("")* 2. 创建节点 带有数据:create().forPath("",data)* 3. 设置节点的类型:create().withMode().forPath("",data)* 4. 创建多级节点  /app1/p1 :create().creatingParentsIfNeeded().forPath("",data)*/@Testpublic void testCreate2() throws Exception {//1. 基本创建//如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储String path = client.create().forPath("/app1");  // 这里是在根节点后的节点路径System.out.println(path);}@Testpublic void testCreate() throws Exception {//2. 创建节点 带有数据//如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储String path = client.create().forPath("/app2", "hehe".getBytes());System.out.println(path);}@Testpublic void testCreate3() throws Exception {//3. 设置节点的类型//默认类型:持久化String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");System.out.println(path);}@Testpublic void testCreate4() throws Exception {//4. 创建多级节点  /app1/p1//creatingParentsIfNeeded():如果父节点不存在,则创建父节点String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1");System.out.println(path);}

查询节点

/*** 查询节点:* 1. 查询数据:get: getData().forPath()* 2. 查询子节点: ls: getChildren().forPath()* 3. 查询节点状态信息:ls -s:getData().storingStatIn(状态对象).forPath()*/@Testpublic void testGet1() throws Exception {//1. 查询数据:getbyte[] data = client.getData().forPath("/app1");System.out.println(new String(data));}@Testpublic void testGet2() throws Exception {// 2. 查询子节点: lsList<String> path = client.getChildren().forPath("/"); // 查询整棵树System.out.println(path);}@Testpublic void testGet3() throws Exception {Stat status = new Stat();System.out.println(status);//3. 查询节点状态信息:ls -sclient.getData().storingStatIn(status).forPath("/app1");System.out.println(status);}

修改节点

    /*** 修改数据* 1. 基本修改数据:setData().forPath()* 2. 根据版本修改: setData().withVersion().forPath()* * version 是通过查询出来的。目的就是为了让其他客户端或者线程不干扰我。** @throws Exception*/@Testpublic void testSet() throws Exception {client.setData().forPath("/app1", "itcast".getBytes());}@Testpublic void testSetForVersion() throws Exception {Stat status = new Stat();//3. 查询节点状态信息:ls -sclient.getData().storingStatIn(status).forPath("/app1");int version = status.getVersion();//查询出来的 3System.out.println(version);client.setData().withVersion(version).forPath("/app1", "hehe".getBytes());}

删除节点

 /*** 删除节点: delete deleteall* 1. 删除单个节点:delete().forPath("/app1");* 2. 删除带有子节点的节点:delete().deletingChildrenIfNeeded().forPath("/app1");* 3. 必须成功的删除:为了防止网络抖动。本质就是重试。  client.delete().guaranteed().forPath("/app2");* 4. 回调:inBackground* @throws Exception*/@Testpublic void testDelete() throws Exception {// 1. 删除单个节点client.delete().forPath("/app1");}@Testpublic void testDelete2() throws Exception {//2. 删除带有子节点的节点client.delete().deletingChildrenIfNeeded().forPath("/app4");}@Testpublic void testDelete3() throws Exception {//3. 必须成功的删除client.delete().guaranteed().forPath("/app2");}@Testpublic void testDelete4() throws Exception {//4. 回调client.delete().guaranteed().inBackground(new BackgroundCallback(){@Overridepublic void processResult(CuratorFramework client, CuratorEvent event) throws Exception {System.out.println("我被删除了~");System.out.println(event);}}).forPath("/app1");}@Afterpublic void close() {if (client != null) {client.close();}}

Watch事件监听

概念

        Zookeeper的Watch事件监听是一种机制,用于在Zookeeper集群中监视观察节点状态的变化。当某个节点发生变化时(例如数据内容的更改、节点的创建或删除等),Zookeeper会通知与该节点相关联的应用程序,以便应用程序能够及时作出相应的处理。 Watch事件监听可以帮助应用程序实时感知和处理节点状态的变化,并在节点状态发生变化时触发相应的回调函数或事件处理机制。这种机制使得应用程序能够根据事件的发生而采取适当的行动,从而实现分布式系统中各个节点之间的协调和同步。

Watch事件监听可以类比一下 volatile 关键字修饰的变量的保证多线程可见性的操作

API演示 
 /*** 建立连接*/@Beforepublic void testConnect() {/*** @param connectString       连接字符串。zk server 地址和端口 "192.168.149.135:2181,192.168.149.136:2181"* @param sessionTimeoutMs    会话超时时间 单位ms* @param connectionTimeoutMs 连接超时时间 单位ms* @param retryPolicy         重试策略*//* //重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,10);//1.第一种方式CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.149.135:2181",60 * 1000, 15 * 1000, retryPolicy);*///重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);//2.第二种方式//CuratorFrameworkFactory.builder();client = CuratorFrameworkFactory.builder().connectString("192.168.149.135:2181").sessionTimeoutMs(60 * 1000).connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("itheima").build();//开启连接client.start();}@Afterpublic void close() {if (client != null) {client.close();}}/*** 演示 NodeCache:给指定一个节点注册监听器*/@Testpublic void testNodeCache() throws Exception {//1. 创建NodeCache对象final NodeCache nodeCache = new NodeCache(client,"/app1");//2. 注册监听nodeCache.getListenable().addListener(new NodeCacheListener() {@Overridepublic void nodeChanged() throws Exception {System.out.println("节点变化了~");//获取修改节点后的数据byte[] data = nodeCache.getCurrentData().getData();System.out.println(new String(data));}});//3. 开启监听.如果设置为true,则开启监听是,加载缓冲数据nodeCache.start(true);}/*** 演示 PathChildrenCache:监听某个节点的所有子节点们*/@Testpublic void testPathChildrenCache() throws Exception {//1.创建监听对象PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/app2",true);//2. 绑定监听器pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {@Overridepublic void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {System.out.println("子节点变化了~");System.out.println(event);//监听子节点的数据变更,并且拿到变更后的数据//1.获取类型PathChildrenCacheEvent.Type type = event.getType();//2.判断类型是否是updateif(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){System.out.println("数据变了!!!");byte[] data = event.getData().getData();System.out.println(new String(data));}}});//3. 开启pathChildrenCache.start();}/*** 演示 TreeCache:监听某个节点自己和所有子节点们*/@Testpublic void testTreeCache() throws Exception {//1. 创建监听器TreeCache treeCache = new TreeCache(client,"/app2");//2. 注册监听treeCache.getListenable().addListener(new TreeCacheListener() {@Overridepublic void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {System.out.println("节点变化了");System.out.println(event);}});//3. 开启treeCache.start();}

分布式锁实现

分布式锁概述


ZooKeeper分布式锁原理 

基于节点顺序依次获取锁可见,Zookeeper实现的锁是公平锁


Curator实现分布式锁

API 

在Curator中有五种锁方案:

  • InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
  • InterProcessMutex:分布式可重入排它锁
  • InterProcessReadWriteLock:分布式读写锁
  • InterProcessMultiLock:将多个锁作为单个实体管理的容器
  • InterProcessSemaphoreV2:共享信号量

1. 配置

添加curator客户端配置:

@Configuration
public class CuratorConfig {@Beanpublic CuratorFramework curatorFramework(){// 重试策略,这里使用的是指数补偿重试策略,重试3次,初始重试间隔1000ms,每次重试之后重试间隔递增。RetryPolicy retry = new ExponentialBackoffRetry(1000, 3);// 初始化Curator客户端:指定链接信息 及 重试策略CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.1.111:2181", retry);client.start(); // 开始链接,如果不调用该方法,很多方法无法工作return client;}
}

2. 可重入锁InterProcessMutex

ReentrantJDKReentrantLock类似, 意味着同一个客户端在拥有锁的同时,可以多次获取,不会被阻塞。它是由类InterProcessMutex来实现。

// 常用构造方法
public InterProcessMutex(CuratorFramework client, String path)
// 获取锁
public void acquire();
// 带超时时间的可重入锁
public boolean acquire(long time, TimeUnit unit);
// 释放锁
public void release();

注意:如想重入,则需要使用同一个InterProcessMutex对象。

3. 不可重入锁InterProcessSemaphoreMutex

具体实现:InterProcessSemaphoreMutexInterProcessMutex调用方法类似,区别在于该锁是不可重入的,在同一个线程中不可重入。

public InterProcessSemaphoreMutex(CuratorFramework client, String path);
public void acquire();
public boolean acquire(long time, TimeUnit unit);
public void release();

4. 可重入读写锁InterProcessReadWriteLock

类似JDKReentrantReadWriteLock。一个拥有写锁的线程可重入读锁,但是读锁却不能进入写锁。这也意味着写锁可以降级成读锁。从读锁升级成写锁是不成的。主要实现类InterProcessReadWriteLock

// 构造方法
public InterProcessReadWriteLock(CuratorFramework client, String basePath);
// 获取读锁对象
InterProcessMutex readLock();
// 获取写锁对象
InterProcessMutex writeLock();

注意:写锁在释放之前会一直阻塞请求线程,而读锁不会

5. 联锁InterProcessMultiLock

Multi Shared Lock是一个锁的容器。当调用acquire, 所有的锁都会被acquire,如果请求失败,所有的锁都会被release。同样调用release时所有的锁都被release(失败被忽略)。基本上,它就是组锁的代表,在它上面的请求释放操作都会传递给它包含的所有的锁。实现类InterProcessMultiLock

// 构造函数需要包含的锁的集合,或者一组ZooKeeper的path
public InterProcessMultiLock(List<InterProcessLock> locks);
public InterProcessMultiLock(CuratorFramework client, List<String> paths);// 获取锁
public void acquire();
public boolean acquire(long time, TimeUnit unit);// 释放锁
public synchronized void release();

6. 信号量InterProcessSemaphoreV2

一个计数的信号量类似JDKSemaphoreJDKSemaphore维护的一组许可(permits),而Cubator中称之为租约(Lease)。注意,所有的实例必须使用相同的numberOfLeases值。调用acquire会返回一个租约对象。客户端必须在finallyclose这些租约对象,否则这些租约会丢失掉。但是,如果客户端session由于某种原因比如crash丢掉, 那么这些客户端持有的租约会自动close, 这样其它客户端可以继续使用这些租约。主要实现类InterProcessSemaphoreV2

// 构造方法
public InterProcessSemaphoreV2(CuratorFramework client, String path, int maxLeases);// 注意一次你可以请求多个租约,如果Semaphore当前的租约不够,则请求线程会被阻塞。
// 同时还提供了超时的重载方法
public Lease acquire();
public Collection<Lease> acquire(int qty);
public Lease acquire(long time, TimeUnit unit);
public Collection<Lease> acquire(int qty, long time, TimeUnit unit)// 租约还可以通过下面的方式返还
public void returnAll(Collection<Lease> leases);
public void returnLease(Lease lease);

7. 共享计数器

利用ZooKeeper可以实现一个集群共享的计数器。只要使用相同的path就可以得到最新的计数器值, 这是由ZooKeeper的一致性保证的。Curator有两个计数器, 一个是用int来计数,一个用long来计数。

7.1. SharedCount

共享计数器SharedCount相关方法如下:

// 构造方法
public SharedCount(CuratorFramework client, String path, int seedValue);
// 获取共享计数的值
public int getCount();
// 设置共享计数的值
public void setCount(int newCount) throws Exception;
// 当版本号没有变化时,才会更新共享变量的值
public boolean  trySetCount(VersionedValue<Integer> previous, int newCount);
// 通过监听器监听共享计数的变化
public void addListener(SharedCountListener listener);
public void addListener(final SharedCountListener listener, Executor executor);
// 共享计数在使用之前必须开启
public void start() throws Exception;
// 关闭共享计数
public void close() throws IOException;

ZooKeeper 集群搭建

选举机制

        ZooKeeper的选举机制是指在ZooKeeper集群中选择一个节点作为Leader节点的过程。选举机制确保在集群中只有一个节点充当Leader,而其他节点作为Followers来同步数据。

        全局唯一标识:每个节点在加入ZooKeeper集群时,会被分配一个全局唯一标识(Zxid),用于标识节点的唯一性和顺序性。这个标识由Leader节点负责分配。

  • Server,选举状态
  • LOOKING,竞选状态。
  • FOLLOWING,随从状态,同步leader状态,参与投票。
  • LEADING,领导者状态。

选举过程

数据同步

服务器1

服务器1启动,发起投票,投票格式为(Zxid,ServerID),投出的票为(0,1),此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING。

服务器2

服务器2启动,发起投票,投出的票为(0,2),服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的ServerID比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING。

服务器3

服务器3启动,发起投票,投出的票为(0,3),此时服务器1和服务器2发现服务器3的ServerID比自己目前投票推举的(服务器2)大,更改选票为推举服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING。

服务器4

服务器4启动,发起投票。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING。

服务器5

服务器5启动,同4一样当小弟。

注:Zookeeper集群的中每个服务器的数据都是一致的,除非网络波动极大,才会导致Zxid不一致,故而每个服务器的Zxid一致。如果真的遇到Zxid不一致,那么最大的Zxid的服务器会自动当选leader,如果相当则按照上述规则进行选举。

四、总结

本文介绍了Zookeeper的选举机制,需要注意一下几点:

  • 同一集群中Zxid是一致的,除非网络很差。

  • Zookeeper选举成功遵循半数机制,即选票成功超过50%就行。

  • leader故障后会重新按照规则进行选举,优先选择Zxid大的。

异常情况处理

在选举过程中,可能会发生以下异常情况:

  • Leader节点失去连接或崩溃:当Leader节点失去连接或崩溃时,其他节点无法接收到Leader的心跳消息,会开始新一轮的选举,选举出新的Leader。
  • 拥有最新数据的节点脱离集群:如果一个拥有最新数据的节点脱离了集群,其他节点会将其标记为不可达,并继续选举新的Leader。

集群中的角色定位

相关文章:

Zookeeper【Curator客户端Java版】从0到1——万字学习笔记

目录 初识Zookeeper Zookeeper作用 维护配置信息 分布式锁服务 集群管理 生产分布式唯一ID Zookeeper的设计目标 Zookeeper 工作机制 数据模型 ZooKeeper 命令操作 服务端常用命令 客户端常用命令 ZooKeeper JavaAPI操作 Curator 介绍 Curator API 常用操作 导入依赖 建立连接 …...

生物标志物发现中的无偏数据分析策略

目录 0. 导论基本概念 1. 生物标志物发现的注意事项2. 数据预处理2.1 高质量原始数据和缺失值处理2.2 数据过滤2.3 数据归一化 3. 数据质量评估3.1 混杂因素3.2 类别分离3.3 功效分析3.4 批次效应 4. 生物标志物发现4.1 策略4.2 数据分析工具4.3 模型优化策略 0. 导论 组学技术…...

华为校招机试题- 机器人活动区域-2023年

题目描述: 现有一个机器人,可放置于 M N的网格中任意位置,每个网格包含一个非负整数编号。当相邻网格的数字编号差值的绝对值小于等于 1 时,机器人可在网格间移动 问题:求机器人可活动的最大范围对应的网格点数目。 说明: 1)网格左上角坐标为 (0, 0),右下角坐标为 (m-…...

半屏小程序

准备工作 tip 管理后台配置 设置-》第三方设置-》半屏小程序管理-》我调用的 添加小程序 有些手机会唤起失败&#xff0c;直接唤起了全屏的小程序&#xff0c;所以我们为了兼容&#xff0c;需要在app.config.ts加上 {"embeddedAppIdList": ["wxxxxxxxx"]/…...

2023年最新Python大数据之Python基础【七】管理系统

文章目录 7、学生管理系统8、函数递归9、lambda函数后记 7、学生管理系统 # 需求拆分:1.展示学生管理系统的功能有哪些,引导用户键入序号选择功能 2.获取用户键入的功能 3.分析具体要执行哪一项功能 4.执行功能 def print_all_option():"""用户功能界面展示&qu…...

【网安】网络安全防止个人信息泄露

网络安全防止个人信息泄露 1、尝试检查自己的网络隐私数据是否泄漏过&#xff0c;可以使用下面的网站2、使用安全非盈利组织的浏览器3、安装浏览器插件&#xff0c;防止网络跟踪4、保持安全的访问方式 1、尝试检查自己的网络隐私数据是否泄漏过&#xff0c;可以使用下面的网站 …...

ChatGPT,AIGC 数据库应用 Mysql 常见优化30例

使用ChatGPT,AIGC总结出Mysql的常见优化30例。 1. 建立合适的索引:在Mysql中,索引是重要的优化手段,可以提高查询效率。确保表的索引充分利用,可以减少查询所需的时间。如:create index idx_name on table_name(column_name); 2. 避免使用select * :尽可能指定要返回的…...

并查集路径压缩

并查集里的 find 函数里可以进行路径压缩&#xff0c;是为了更快速的查找一个点的根节点。对于一个集合树来说&#xff0c;它的根节点下面可以依附着许多的节点&#xff0c;因此&#xff0c;我们可以尝试在 find 的过程中&#xff0c;从底向上&#xff0c;如果此时访问的节点不…...

spring和springMVC的说明

Spring和Spring MVC都是Java应用程序开发中常用的框架&#xff0c;它们提供了一种结构化的方法来构建企业级Java应用程序。下面我将对它们进行详细的说明&#xff1a; Spring&#xff1a; 概述&#xff1a; Spring是一个综合的Java应用程序开发框架&#xff0c;旨在简化企业级…...

软件工程与计算总结(十)软件体系结构设计与构建

目录 ​编辑 一.体系结构设计过程 1.分析关键需求和项目约束 2.选择体系结构风格 3.体系结构逻辑设计 4.体系结构实现 5.完善体系结构设计 6.定义构件接口 二.体系结构原型构建 1.包的创建 2.重要文件的创建 3.定义构件之间的接口 4.关键需求的实现 三.体系结构的…...

【实操】基于ChatGPT构建知识库

前言 最近有些实践&#xff0c;因为后面要去研究fine-tune了&#xff0c;想着记录一下chatgpt向量数据库构建知识库的一些实操经验&#xff0c;不记我很快就忘了&#xff0c;哈哈。 首先&#xff0c;提一下为啥会出现向量数据库这个技术方案&#xff1f; 大家经过实践发现&…...

ribbonx编程笔记-读写注册表与使用自定义对话框

​ Windows 注册表是一个数据库,用于存储与计算机不同方面相关的设置,例如用户设置、应用程序设备、硬件设置,等等。 VBA 提供了与注册表直接交互的方式,这不仅允许我们获取其它程序和硬件的信息,而且也能够使我们选择应用程序中的重要信息并将其存储在注册表中。本文中,…...

网工记背配置命令(3)----POE配置示例

POE 供电就是通过以太网供电&#xff0c;这种方式仅凭借那根连接通信终端的网线就可完成为它们供电。POE提供的是-53V~0v 的直流电&#xff0c;供电距离最长可达 100m。PoE 款型的交换机的软件大包天然支持 POE&#xff0c;无需 license&#xff0c;通过执行 poe-enable 命令使…...

网络安全(黑客技术)—0基础学习手册

目录 一、自学网络安全学习的误区和陷阱 二、学习网络安全的一些前期准备 三、网络安全学习路线 四、学习资料的推荐 想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类…...

[部署网站]01安装宝塔面板搭建WordPress

宝塔面板安装WordPress&#xff08;超详细&#xff09;_Wordpress主题网 参考教程 宝塔面板 - 简单好用的Linux/Windows服务器运维管理面板 官网 1.首先你需要一个服务器或者主机 &#xff08;Windows系统或者Linux系统都可以&#xff09; 推荐Linux系统更稳定&#xff0c;…...

Can We Edit Multimodal Large Language Models?

本文是LLM系列文章&#xff0c;针对《Can We Edit Multimodal Large Language Models?》的翻译。 我们可以编辑多模态大型语言模型吗? 摘要1 引言2 相关工作3 编辑多模态LLM4 实验5 结论 摘要 本文主要研究多模态大语言模型(Multimodal Large Language Models, mllm)的编辑…...

使用jsqlparser创建MySQL建表语句

语法 create table [IF NOT EXISTS] 表名 ( 字段名 类型 [约束条件], 字段名 类型 [约束条件], 字段名 类型 [约束条件], 字段名 类型 [约束条件] ); 字段定义在括号内约束条件可以有多个多个字段定义之间用都会隔开 常见约束 NOT NULL 非空DEFAULT 0 默认值AUTO_INCREMENT…...

字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C , CF1109B)

字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C &#xff0c; CF1109B) CF 245 H. Queries for Number of Palindromes&#xff08;字符串 dp&#xff09; Problem - H - Codeforces 大意&#xff1a;给出一个字符串S (|S| ≤ 5000) , 给出 Q 次询问 &#xff0c; 每…...

Linux:Mac VMware Fusion13以及CentOS7安装包

Linux&#xff1a;Mac VMware Fusion13以及CentOS7安装包 1. Mac VMware Fusion132. CentOS7安装包3. 安装 1. Mac VMware Fusion13 下载官网地址&#xff1a;https:www.vmware.com/products/fusion/fusion-evaluation.html 2. CentOS7安装包 注意是m芯片需要使用arm架构的i…...

【微服务部署】十、使用Docker Compose搭建高可用Redis集群

现如今&#xff0c;业务系统对于缓存Redis的依赖似乎是必不可少的&#xff0c;我们可以在各种各样的系统中看到Redis的身影。考虑到系统运行的稳定性&#xff0c;Redis的应用和MySQL数据库一样需要做到高可用部署。 一、Redis 的多种高可用方案 常见的Redis的高可用方案有以下…...

【数据结构】树状数组C++详解

文章目录 引入树状数组定义什么是单点修改和区间查询工作原理区间查询代码实现单点修改实现代码242. 一个简单的整数问题AC代码如下:练习:AC代码如下:引入 242. 一个简单的整数问题 给定长度为 N的数列 A A A<...

机器人制作开源方案 | 扫地机器人

1. 功能描述 扫地机器人是现代家庭清洁的得力助手&#xff0c;能够自主规划清扫路径&#xff0c;避开障碍物&#xff0c;有效覆盖整个清洁区域。扫地机器人的出现极大地减轻了家庭清洁的负担&#xff0c;节省了时间和精力&#xff0c;它可以定期清理地面&#xff0c;确保家居环…...

10.2手动推导linux中file, cdev, inode之间的关系

是时候可以手动推导一下linux里面基类父类和子类的关系了 代码放最后把 简单说明版 详细流程 第一步注册驱动 cdev结构体能看做是一个基类,那么链表里面都是字符设备驱动的cdev连载一起,啥串口,lcd的,通过cdev->list_head连接 那cdev结构体里有主次设备号 第一步 使用r…...

JavaScript基础知识13——运算符:一元运算符,二元运算符

哈喽&#xff0c;大家好&#xff0c;我是雷工。 JavaScript的运算符可以根据所需表达式的个数&#xff0c;分为一元运算符、二元运算符、三元运算符。 一、一元运算符 1、一元运算符&#xff1a;只需要一个表达式就可以运算的运算符。 示例&#xff1a;正负号 一元运算符有两…...

异步使用langchain

文章目录 一.先利用langchain官方文档的AI功能问问二.langchain async api三.串行&#xff0c;异步速度比较 一.先利用langchain官方文档的AI功能问问 然后看他给的 Verified Sources 这个页面里面虽然有些函数是异步函数&#xff0c;但是并非专门讲解异步的 二.langchain asy…...

抖音开放平台第三方代小程序开发,授权事件、消息与事件通知总结

大家好&#xff0c;我是小悟 关于抖音开放平台第三方代小程序开发的两个事件接收推送通知&#xff0c;是开放平台代小程序实现业务的重要功能。 授权事件推送和消息与事件推送类型都以Event的值判断。 授权事件推送通知 授权事件推送包括&#xff1a;推送票据、授权成功、授…...

华为9.20笔试 复现

第一题 丢失报文的位置 思路&#xff1a;从数组最小索引开始遍历 #include <iostream> #include <vector> using namespace std; // 求最小索引值 int getMinIdx(vector<int> &arr) {int minidx 0;for (int i 0; i < arr.size(); i){if (arr[i] …...

二十五、【色调调整基础】

文章目录 1、亮度/对比度a、亮度b、对比度 2、曝光度3、阈值4、色阶5、反相6、黑白7、渐变映射 1、亮度/对比度 a、亮度 亮度是指画面的明亮程度 b、对比度 对比度指的是一幅图像中&#xff0c;明暗区域最亮和最暗之间不同亮度层级的测量&#xff0c;如下图所示&#xff0…...

Android Studio SDK manager加载packages不全

打开Android Studio里的SDK manager&#xff0c;发现除了已安装的&#xff0c;其他的都不显示。 解决方法&#xff1a; 设置代理&#xff1a; 方便复制> http://mirrors.neusoft.edu.cn/ 重启Android Studio...

[esp32-wroom]基础开发

1、点亮LED灯 int led_pin2; void setup() {// put your setup code here, to run once:pinMode(led_pin,OUTPUT);}void loop() {// put your main code here, to run repeatedly:digitalWrite(led_pin,HIGH);delay(1000);digitalWrite(led_pin,LOW);delay(1000); } 2、LED流…...

网站模板上传工具/seo综合查询平台官网

angular分页插件tm.pagination二次触发问题解决歪方案参考文章&#xff1a; &#xff08;1&#xff09;angular分页插件tm.pagination二次触发问题解决歪方案 &#xff08;2&#xff09;https://www.cnblogs.com/qinglangsunny/p/9307773.html 备忘一下。...

海淘返利网站怎么做/网页分析工具

结合二叉树和Graham扫描技术的高效Delaunay三角网构建算法 摘 要:为了提高不规则三角网的构建速度,提出了一种高效构建Delaunay三角网算法。首先对平面上的离散点集按一定的阈值进行分块,建立子块索引二叉树,然后利用Graham扫描技术对各子块构建Delaunay三角网,最后自底向上…...

网站免费建站http/网络热词2021流行语

对于切词确实是一个复杂的功能&#xff0c;足以写上好几篇论文&#xff0c;但是如果仅仅想对一个句子、一个段落、一篇文章进行切词&#xff0c;可以利用中国自然语言开源组织中各位大牛写好的工具。已经打包成jar包&#xff0c;可以直接调用了&#xff0c;无须自己再考虑复杂的…...

wordpress做的网站吗/seo诊断书案例

msvcr110.dll丢失怎么办呢?下文小编就为大家带来msvcr110.dll丢失修复的解决方法&#xff0c;很多朋友在运行某软件或编译程序时提示缺少、找不到msvcr110.dll等类似提示&#xff0c;下面就和小编一起去看下解决方法吧。msvcr110.dll下载地址&#xff1a;msvcr110.dll_丢失msv…...

英文互动网站建设/网络关键词优化方法

ArcGIS案例学习笔记-点群密度统计 联系方式&#xff1a;向日葵&#xff0c;135-4855-4328&#xff0c;xiexiaokui#qq.com 目的&#xff1a;对于点群&#xff0c;统计分布密度 数据&#xff1a; 方法&#xff1a; 1. 生成格网 2. 统计个数&#xff0c;制作专题图 联系方式…...

做钢结构网站有哪些/免费seo在线优化

我们都知道调用WCF直接在Service References中引用可以远程调用的WCF Url就行了。 但是我们想过没&#xff0c;在Development环境中可以这样做&#xff0c;但是QA、UAT、Production上我们怎么做呢&#xff1f; WCF的通信方式主要有Http和Tcp&#xff0c;这次我们用Http。 好了&…...