Zookeeper完全教程:集群搭建、常用命令、Java API使用代码示例-程序员宅基地

技术标签: java  zookeeper  后台编程  java-zookeeper  大数据  

Zookeeper

​ Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台

课程内容的介绍

  1. Zookeeper的介绍和安装
  2. Zookeeper客户端使用
  3. ZookeeperJavaAPI使用

一、Zookeeper的介绍和安装

1. 为什么要使用Zookeeper

​ 我们为了学习Dubbo,而在dubbo中需要一个注册中心,而Zookeeper是我们在使用Dubbo是官方推荐的注册中心,所以我们先来介绍Zookeeper
在这里插入图片描述

在这里插入图片描述

2. Zookeeper介绍

在这里插入图片描述

2.1 Zookeeper概述

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
  Zookeeper是一个分布式协调服务;就是为用户的分布式应用程序提供协调服务

序号 功能
1 为别的分布式程序服务的
2 本身就是一个分布式程序
3 主从协调 服务器节点动态上下线 统一配置管理 分布式共享锁 统一名称服务
4 管理(存储,读取)用户程序提交的数据 并为用户程序提供数据节点监听服务

2.2 Zookeeper的集群机制

Zookeeper是为其他分布式程序提供服务的,所以本身自己不能随便就挂了,所以zookeeper自身的集群机制就很重要。zookeeper的集群机制采用的是半数存活机制,也就是整个集群节点中有半数以上的节点存活,那么整个集群环境可用。这也就是说们的集群节点最好是奇数个节点。

Zookeeper集群节点的角色

Leader

Leader服务器是Zookeeper集群工作的核心,其主要工作如下

  1. 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
  2. 集群内部各服务器的调度者

Follower

Follower是Zookeeper集群的跟随者,其主要工作如下

  1. 处理客户端非事务性请求(读取数据),转发事务请求给Leader服务器。
  2. 参与事务请求Proposal的投票。
  3. 参与Leader选举投票。

Observer
Observer充当观察者角色,观察Zookeeper集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进行独立处理,对于事务请求,则会转发给Leader服务器进行处理。Observer不会参与任何形式的投票,包括事务请求Proposal的投票和Leader选举投票

3. 集群环境准备

​ 通过上面的介绍我们了解到zookeeper的集群环境应该配置奇数个节点,所以我们在本文中搭建的zookeeper环境准备在3个节点上搭建。接下来我们介绍下需要准备的环境。

3.1 准备3个节点

​ 准备3个centos7.0的虚拟机节点,并且安装配置好JDK版本最好是8.不清楚的可参考此地址Linux之jdk安装,并配置好相关的网络配置。

ip 主机名
192.168.100.120 bobo01
192.168.100.121 bobo02
192.168.100.122 bobo03

通过VMware的克隆或者直接复制文件夹的方式来创建另外两个新的节点

3.2 网络配置

修改ifcfg-ens33配置文件
在这里插入图片描述

重启网络服务

service network restart

ping测试
在这里插入图片描述

三个节点的网络配置都ok的化我们就可以通过XShell来连接了

3.3 节点的映射关系

每个节点设置相应的ip和主机名的映射关系,方便集群环境的部署

修改hosts配置文件中的信息
在这里插入图片描述

3.4 配置免密登录

生成公钥和私钥

ssh-keygen

输入命令后根据提示,四次回车即可
在这里插入图片描述

发送公钥给需要免密登录的节点

ssh-copy-id bobo01
ssh-copy-id bobo02
ssh-copy-id bobo03

在这里插入图片描述

节点和节点发送文件通过scp命令实现

scp -r b.txt bobo01:/root/

在这里插入图片描述

3.5 关闭防火墙

查看防火墙状态

firewall-cmd --state

停止防火墙

systemctl stop firewall.service

禁止开机启动

systemctl disable firewall.service

4. Zookeeper集群环境搭建

4.1 获取安装文件

下载地址:https://mirrors.bfsu.edu.cn/apache/zookeeper/

通过wget命令将安装文件下载到opt目录下

注意:

apache-zookeeper-3.5.9-bin.tar.gz和apache-zookeeper-3.5.9.tar.gz的区别 -bin是编译后的文件 我们用这个

wget https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.5.9/apache-zookeeper-3.5.9-bin.tar.gz

在这里插入图片描述

解压缩文件
在这里插入图片描述

进入Zookeeper目录
在这里插入图片描述

4.2 修改配置

修改zoo.cfg文件,系统默认的名称是 zoo_smple.cfg我们需要重命名为zoo.cfg
在这里插入图片描述

修改cfg的内容

修改了两块:

1是Zookeeper中存储数据的文件夹,还有就是Zookeeper集群环境节点信息
在这里插入图片描述

配置myid文件

​ 我们需要在Zookeeper的数据存储的目录中创建一个myid文件,文件中的内容只有一行信息,即表示我们集群几点的标识,范围是1-255,每个节点的myid的数字和我们在zoo.cfg中配置的server.数字是对应的

1

4.3 分发文件

​ 当我们配置好了一个Zookeeper节点后,我们就可以将Zookeeper文件夹分发给其他几个节点了

scp -r zookeeper bobo02:`pwd`
scp -r zookeeper bobo03:`pwd`

分发成功后我们需要修改各个节点中的myid的信息为配置文件中对应的数字

4.4 启动测试

整个集群环境都配置好了之后我们就可以测试启动了

启动命令

./bin/zkServer.sh start

当我们仅仅启动一个节点的时候,因为半数存活机制,3个节点只启动一个节点是没有效果的,
在这里插入图片描述

当我们启动第二个节点后发现集群环境可以使用了

在这里插入图片描述

然后第一个节点的状态也改变了

在这里插入图片描述

然后再把第三个节点也启动起来

在这里插入图片描述

5. Zookeeper的选举机制

为什么要进行Leader选举?
Leader 主要作用是保证分布式数据一致性,即每个节点的存储的数据同步。遇到以下两种情况需要进行Leader选举

  • 服务器初始化启动
  • 服务器运行期间无法和Leader保持连接,Leader节点崩溃,逻辑时钟崩溃。

5.1 服务器初始化时Leader选举

Zookeeper由于其自身的性质,一般建议选取奇数个节点进行搭建分布式服务器集群。以3个节点组成的服务器集群为例,说明服务器初始化时的选举过程。启动第一台安装Zookeeper的节点时,无法单独进行选举,启动第二台时,两节点之间进行通信,开始选举Leader。

  1. 每个Server投出一票。他们两都选自己为Leader,投票的内容为(SID,ZXID)。
    SID即Server的id,安装zookeeper时配置文件中所配置的myid;ZXID,事务id,
    为节点的更新程度,ZXID越大,代表Server对Znode的操作越新。由于服务器初始化,
    每个Sever上的Znode为0,所以Server1投的票为(1,0),Server2为(2,0)。
    两Server将各自投票发给集群中其他机器。

  2. 每个Server接收来自其他Server的投票。集群中的每个Server先判断投票有效性,
    如检查是不是本轮的投票,是不是来Looking状态的服务器投的票。

  3. 对投票结果进行处理。先了解下处理规则

  • 首先对比ZXID。ZXID大的服务器优先作为Leader

  • 若ZXID相同,比如初始化的时候,每个Server的ZXID都为0,

  • 就会比较myid,myid大的选出来做Leader。

    对于Server而言,他接受到的投票为(2,0),因为自身的票为(1,0),所以此时它会选举Server2为Leader,
    将自己的更新为(2,0)。而Server2收到的投票为Server1的(1,0)由于比他自己小,
    Server2的投票不变。Server1和Server2再次将票投出,投出的票都为(2,0)。

  1. 统计投票。每次投票之后,服务器都会统计投票信息,如果判定某个Server有过半的票数投它,
    那么该Server将会作为Leader。对于Server1和Server2而言,统计出已经有两台机器接收了(2,0)的投票信息,
    此时认为选出了Leader。

  2. 改变服务器状态。当确定了Leader之后,每个Server更新自己的状态,
    Leader将状态更新为Leading,Follower将状态更新为Following。

在这里插入图片描述

5.2 服务器运行期间的Leader选举

Zookeeper运行期间,如果有新的Server加入,或者非Leader的Server宕机,那么Leader将会同步数据到新Server或者寻找其他备用Server替代宕机的Server。若Leader宕机,此时集群暂停对外服务,开始在内部选举新的Leader。假设当前集群中有Server1、Server2、Server3三台服务器,Server2为当前集群的Leader,由于意外情况,Server2宕机了,便开始进入选举状态。过程如下

  1. 变更状态。其他的非Observer服务器将自己的状态改变为Looking,开始进入Leader选举。

  2. 每个Server发出一个投票(myid,ZXID),由于此集群已经运行过,所以每个Server上的ZXID可能不同。
    假设Server1的ZXID为145,Server3的为122,第一轮投票中,Server1和Server3都投自己,
    票分别为(1,145)、(3,122),将自己的票发送给集群中所有机器。

  3. 每个Server接收接收来自其他Server的投票,接下来的步骤与初始化时相同。

二、Zookeeper客户端使用

1. 配置Zookeeper的环境变量

​ 为了简化我们每次操作Zookeeper而不用进入到Zookeeper的安装目录,我们可以将Zookeeper的安装信息配置到系统的环境变量中

vim /etc/profile

添加的内容

export ZOOKEPPER_HOME=/opt/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin

执行source命令

source /etc/profile

我们就可以在节点的任意位置操作Zookeeper了

通过scp命令将profile文件发送到其他几个节点上

scp /etc/profile bobo02:/etc/

2.客户端连接

通过bin目录下的zkCli.sh 命令连接即可

zkCli.sh

在这里插入图片描述

zkCli.sh默认连接的是当前节点的Zookeeper节点,如果我们要连接其他节点执行如下命令即可

zkCli.sh -timeout 5000 -server bobo02:2181

在这里插入图片描述

3.数据操作

3.1 Zookeeper的数据结构

  1. 层次化的目录结构,命名符合常规文件系统规范
  2. 每个节点在Zookeeper中叫做znode,并且有一个唯一的路径标识
  3. 节点znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)
  4. 客户端应用可以在节点上设置监听器

在这里插入图片描述

3.2 节点类型

1).znode有两种类型:

短暂性(ephemeral)(断开连接自己删除)
持久性(persistent)(断开连接不删除)

2).znode有四种形式的目录节点(默认是persistent)如下

序号 节点类型 描述
1 PERSISTENT 持久节点
2 PERSISTENT_SEQUENTIAL 持久有序节点
3 EPHEMERAL 短暂节点
4 EPHEMERAL_SEQUENTIAL 短暂有序节点

​ 创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,有父节点维护
在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序

3.3 常用命令

​ Zookeeper作为Dubbo的注册中心用来保存我们各个服务的节点信息,显示Zookeeper是可以实现输出的存储操作的,我们来看下Zookeeper中存储操作的基本命令

在这里插入图片描述

ls

​ ls用来查看某个节点下的子节点信息

在这里插入图片描述

增强的命令,查看节点下的子节点及当前节点的属性信息 ls2或者 ls -s 命令

在这里插入图片描述

create

​ 创建节点信息

在这里插入图片描述

get

​ get命令用来查看节点的数据

在这里插入图片描述

如果要查看节点的属性信息那么我们可以通过get -s 来实现

在这里插入图片描述

delete

​ delete只能删除没有子节点的节点要删除非空节点可以通过 rmr 或者 deleteall 命令实现

在这里插入图片描述

set

​ set命令可以用来修改节点的内容。

在这里插入图片描述

3.4 事件监听

3.4.1 数据改变的监听

​ 监听某个节点的数据内容变化,通过get命令 带 -w 参数即可,在3.4版本的Zookeeper中是通过 get path watch 来说实现监控的

在这里插入图片描述

然后我们在其他节点上修改app1节点的数据,会触监听事件

在这里插入图片描述

在这里插入图片描述

注意监听一次节点只会触发一次,如果要实现多次监听,那么可以在触发事件的处理函数中再次追加对节点的监听操作

3.4.2 子节点的改变

​ 监听节点下面的子节点的改变。

[zk: localhost:2181(CONNECTED) 14] ls -w /app1
[]

触发

在这里插入图片描述

在这里插入图片描述

三、Zookeeper Java API使用

​ 介绍如何通过Java代码来操作Zookeeper中的数据

在Zookeeper的安装目录下是提供的有相关的Jar依赖的

在这里插入图片描述

但是我们对于Maven构建项目已经习惯而且是主流,那么我们可以通过maven坐标来管理

<dependencies>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.5.9</version>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

</dependencies>

1. API的使用

1.1 连接ZK服务

package com.bobo.test;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Test;

import java.io.IOException;

public class Test1 {
    

    private String connectString = "192.168.100.121:2181,192.168.122:2181,192.168.100.122:2181";

    private int sessionTimeOut = 5000;

    /**
     * 连接Zookeeper服务端
     */
    @Test
    public void test1() throws IOException {
    
        ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeOut, new Watcher() {
    
            /**
             * 触发监听事件的回调方法
             * @param watchedEvent
             */
            @Override
            public void process(WatchedEvent watchedEvent) {
    
                System.out.println("触发了.....");
            }
        });
        System.out.println("--->" + zooKeeper);
    }
}

在这里插入图片描述

1.2 基本操作

package com.bobo.test;

import jdk.nashorn.internal.ir.CallNode;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class Test1 {
    

    private String connectString = "192.168.100.121:2181,192.168.122:2181,192.168.100.122:2181";

    private int sessionTimeOut = 10000;

    ZooKeeper zooKeeper = null;

    /**
     * 连接Zookeeper服务端
     */
    @Before
    public void test1() throws IOException {
    
        zooKeeper = new ZooKeeper(connectString, sessionTimeOut, new Watcher() {
    
            /**
             * 触发监听事件的回调方法
             * @param watchedEvent
             */
            @Override
            public void process(WatchedEvent watchedEvent) {
    
                System.out.println("触发了.....");
            }
        });
        //System.out.println("--->" + zooKeeper);
    }

    /**
     * 创建节点
     */
    @Test
    public void createNode() throws Exception{
    
        String path = zooKeeper.create("/apptest" // 节点路径
                ,"HelloZookeeper".getBytes() // 节点的数据
                , ZooDefs.Ids.OPEN_ACL_UNSAFE // 权限
        , CreateMode.PERSISTENT // 节点类型
        );
        System.out.println(path);
    }

    /**
     * 判断节点是否存在
     */
    @Test
    public void exist() throws  Exception{
    
        // true表示的是使用Zookeeper中的watch
        Stat stat = zooKeeper.exists("/apptest", true);
        if(stat != null){
    
            System.out.println("节点存在"+ stat.getNumChildren());
        }else{
    
            System.out.println("节点不存在 ....");
        }
    }

    /**
     * 获取某个节点下面的所有的子节点
     */
    @Test
    public void getChildrens() throws Exception{
    
        List<String> childrens = zooKeeper.getChildren("/app1", true);
        for (String children : childrens) {
    
            // System.out.println(children);
            // 获取子节点中的数据
            byte[] data = zooKeeper.getData("/app1/" + children, false, null);
            System.out.println(children+":" + new String(data));
        }
    }

    /**
     * 修改节点的内容
     */
    @Test
    public void setData() throws Exception{
    
        // -1 不指定版本 自动维护
        Stat stat = zooKeeper.setData("/app1/a1", "666666".getBytes(), -1);
        System.out.println(stat);
    }


    /**
     * 删除节点
     */
    @Test
    public void deleteNode() throws Exception{
    
        zooKeeper.delete("/app1",-1);
        
    }


}

1.3 事件监听处理

​ Java程序如何监听Zookeeper中的数据的变化?


    /**
     * 监听Node节点下的子节点的变化
     */
    @Test
    public void nodeChildrenChange() throws Exception{
    
        List<String> list = zooKeeper.getChildren("/app1", new Watcher() {
    

            /**
             *              None(-1),
             *             NodeCreated(1),
             *             NodeDeleted(2),
             *             NodeDataChanged(3),
             *             NodeChildrenChanged(4),
             *             DataWatchRemoved(5),
             *             ChildWatchRemoved(6);
             * @param watchedEvent
             */
            @Override
            public void process(WatchedEvent watchedEvent) {
    
                System.out.println("--->"+ watchedEvent.getType());
            }
        });
        for (String s : list) {
    
            System.out.println(s);
        }

        Thread.sleep(Integer.MAX_VALUE);
    }

    /**
     * 监听节点内容变更
     */
    @Test
    public void nodeDataChanged() throws Exception{
    
        byte[] data = zooKeeper.getData("/app1/a1", new Watcher() {
    
            @Override
            public void process(WatchedEvent watchedEvent) {
    
                System.out.println("--->" + watchedEvent.getType());
            }
        }, null);
        System.out.println("--->" + new String(data));
        Thread.sleep(Integer.MAX_VALUE);
    }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a772304419/article/details/134454114

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签