MySQL集群的基础部署及主从复制详解

news2024/9/20 10:39:52

一、Msql在服务器中的部署方法

官网:http://www.mysql.com
在这里插入图片描述

在企业中90%的服务器操作系统均为Linux

在企业中对于Mysql的安装通常用源码编译的方式来进行

1.1 在Linux下部署MySQL

1.1.1 部署环境
主机IP角色
MySQL-node1172.25.254.13master
MySQL-node2172.25.254.23slave1
MySQL-node3172.25.254.33slave2

注意:在部署MySQL前,先检查主机中的环境是否含有其他数据库,保持环境的纯净性,以防在部署时出现其他错误。另外以下所有案例的实现操作系统都为Rhel 7.9

# 检查是否含有其他数据库,一般为Maridb
[root@mysql-node ~]# rpm -qa | grep mariadb
[root@mysql-node ~]# yum remove mariadb    # 移除mariadb
# 关闭防火墙
[root@mysql-node1 mysql]# systemctl stop firewalld
[root@mysql-node1 mysql]# systemctl mask firewalld
[root@mysql-node1 mysql]# setenforce 0
1.1.2 下载并解压MySQL源码包

(1)进入到MySQL官网

在这里插入图片描述

(2)选择MySQL Community Downloads

在这里插入图片描述

(3)选择Archives

在这里插入图片描述

(4)自行选择版本下载

在这里插入图片描述

(5)选择链接在Linux中进行下载并解压源码包

[root@mysql-node1 ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-5.7.44.tar.gz     # 下载源码包
[root@mysql-node1 ~]# tar zxf mysql-boost-5.7.44.tar.gz    # 解压源码包
[root@mysql-node1 ~]# cd /root/mysql-5.7.44   # 进入到解压目录
1.1.3 安装依赖性
[root@mysql-node3 mysql-5.7.44]# yum install cmake gcc-c++ openssl-devel \
> ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rp^Cen.x86_64 -y     
1.1.4 源码编译安装MySQL
[root@mysql-node1 mysql-5.7.44]# cmake \       
> -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \      # 指定安装路径
> -DMYSQL_DATADIR=/data/mysql \                  # 指定数据目录
> -DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock \     # 指定套接字文件
> -DWITH_INNOBASE_STORAGE_ENGINE=1 \             # 指定启用INNODB存储引擎,默认使用myisam
> -DWITH_EXTRA_CHARSETS=all \                    # 扩展字符集
> -DDEFAULT_CHARSET=utf8mb4 \                    # 指定默认字符集
> -DDEFAULT_COLLATION=utf8mb4_unicode_ci \       # 指定默认校验字符集
> -DWITH_BOOST=/root/mysql-5.7.44/boost/boost_1_59_0/ # 指定C++库依赖

[root@mysql-node1 mysql-5.7.44]# make -j2     # -j2使用两个核心来跑两个进程
[root@mysql-node1 mysql-5.7.44]# make install # 编译完后进行安装
1.1.5 部署MySQL
1.# 创建mysql的用户及用户组
[root@mysql-node1 ~]# useradd -s /sbin/nologin -M mysql
[root@mysql-node1 ~]# mkdir /data/mysql -p
[root@mysql-node1 ~]# chown mysql.mysql -R /data/mysql

2.# 生成启动脚本
[root@mysql-node1 ~]# cd /usr/local/mysql/support-files/
[root@mysql-node1 support-files]# cp mysql.server /etc/init.d/mysqld

3.# 修改环境变量
[root@mysql-node1 ~]# vim ~/.bash_profile 
PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
[root@mysql-node1 ~]# source ~/.bash_profile 

4.# 修改配置文件
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql                # 指定数据目录
socket=/data/mysql/mysql.sock      # 指定套接字
symbolic-links=0                   # 数据只能存放到数据目录中,禁止链接到数据目录

5.# 数据库初始化建立mysql基本数据
[root@mysql-node1 ~]# mysql --user mysql --initialize    # 记得保存生成的初始化密码,在接下来的安全初始化需要用到
[root@mysql-node1 ~]# /etc/init.d/mysqld start           # 开启MySQL服务
[root@mysql-node1 ~]# chkconfig mysqld on                # 设置自启动
[root@mysql-node1 ~]# chkconfig --list                   # 查看自启动的服务

6.# 数据库安全初始化
[root@mysql-node1 ~]# mysql_secure_installation

在这里插入图片描述

测试:登录数据库

[root@mysql-node1 ~]# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.44 Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;      # 查看当前含有的数据库
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

二、MySQL的主从复制

2.1 MySQL的主从复制原理

在这里插入图片描述

三个线程

实际上主从同步的原理就是基于 binlog 进行数据同步的。在主从复制过程中,会基于3 个线程来操作,一个主库线程,两个从库线程。

  • 二进制日志转储线程(Binlog dump thread)是一个主库线程。当从库线程连接的时候, 主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。

  • 从库 I/O 线程会连接到主库,向主库发送请求更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地的中继日志 (Relay log)。

  • 从库 SQL 线程会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。

复制三步骤

步骤1:Master将写操作记录到二进制日志(binlog)。

步骤2:Slave将Master的binary log events拷贝到它的中继日志(relay log);

步骤3:Slave重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的,而且重启后从接入点开始复制。

具体操作

1.slaves端中设置了master端的ip,用户,日志,和日志的Position,通过这些信息取得master的认证及信息

2.master端在设定好binlog启动后会开启binlog dump的线程

3.master端的binlog dump把二进制的更新发送到slave端的

4.slave端开启两个线程,一个是I/O线程,一个是sql线程,i/o线程用于接收master端的二进制日志,此线程会在本地打开relaylog中继日志,并且保存到本地磁盘sql线程读取本地relog中继日志进行回放

5.什么时候我们需要多个slave?

​ 当读取的而操作远远高与写操作时。我们采用一主多从架构数据库外层接入负载均衡层并搭配高可用机制

2.2 架构缺陷

主从架构采用的是异步机制

master更新完成后直接发送二进制日志到slave,但是slaves是否真正保存了数据master端不会检测master端直接保存二进制日志到磁盘

当master端到slave端的网络出现问题时或者master端直接挂掉,二进制日志可能根本没有到达slavemaster出现问题slave端接管master,这个过程中数据就丢失了

这样的问题出现就无法达到数据的强一致性,零数据丢失

2.3 MySQL主从复制的实现

2.3.1 配置master
[root@mysql-n0de1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=13             # 配置主id为13
log-bin=mysql-bin        # 开启二进制日志

[root@mysql-node1 ~]# /etc/init.d/mysqld restart     # 重启mysql服务

# 进入数据库配置用户权限
[root@mysql-nide1 ~]# mysql -uroot -p
Enter password: 
. . . . . .

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY '123123';   # 生成专门用来做复制的用户,此用户是用于slave端做认证用
Query OK, 0 rows affected (0.01 sec.

mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';      # 对这个用户进行授权
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW MASTER STATUS;                              # 查看master的状态
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      595 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

# 查看二进制日志
[root@mysql-nide1 ~]#  cd /data/mysql/
[root@mysql-nide1 mysql]# mysqlbinlog mysql-bin.000001 -vv
2.3.2 配置salve
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=23              # 配置从id为23
super_read_only=on        # 设置slave1只允许读取数据

[root@mysql-node2 ~]# /etc/init.d/mysqld restart

# 进入mysql进行设置
[root@mysql-node2 ~]# mysql -uroot -p       
mysql> change master to master_host='172.25.254.13',master_user='repl',master_password='123123',master_log_file='log_pos=595;               # 设置从库连接主库
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;                     # 开启slave
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G              # 查看从库是否连接成功
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.25.254.13
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 595
               Relay_Log_File: mysql-node2-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes         # IO线程连接成功,实现数据传输
            Slave_SQL_Running: Yes         # SQL进程连接成功,实现数据回放
             . . . . . .

注意:slave主机不能够写入数据,只能读取

2.3.3 主从复制测试
# 在主master中写入数据
[root@mysql-node1 ~]# mysql -uroot -p
Enter password: 
. . . 
mysql> create database haha;             # 建立haha数据库
Query OK, 1 row affected (0.01 sec)

mysql> use haha            # 切换到haha数据库
Database changed
mysql> create table userlist(username varchar(20) not null,password varchar(50) not null);                 # 建立userlist表
Query OK, 0 rows affected (0.02 sec)

mysql> insert into userlist value ('haha','123');   # 写入表格数据
Query OK, 1 row affected (0.04 sec)

mysql> select * from userlist;          # 查看表格数据
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
+----------+----------+
1 row in set (0.00 sec)

# 在slave中查看数据是否同步过来
mysql> select * from haha.userlist;           # 数据从主master同步过来
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
+----------+----------+
1 row in set (0.00 sec)

2.4 当有数据时添加slave2(一主两从)

2.4.1 配置salve2
1.#  # 将主master的mysql远程传送到slave2中
[root@mysql-n0de1 ~]# rsync -al /usr/local/mysql root@172.25.254.33:/usr/local  

2.# 创建mysql的用户及用户组
[root@mysql-node3 ~]# useradd -s /sbin/nologin -M mysql
[root@mysql-node3 ~]# mkdir /data/mysql -p
[root@mysql-node3 ~]# chown mysql.mysql -R /data/mysql

3.# 生成启动脚本
[root@mysql-node3 ~]# cd /usr/local/mysql/support-files/
[root@mysql-node3 support-files]# cp mysql.server /etc/init.d/mysqld

4.# 修改环境变量
[root@mysql-node3 ~]# vim ~/.bash_profile 
PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
[root@mysql-node3 ~]# source ~/.bash_profile 

5.# 修改配置文件
[root@mysql-node3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql                # 指定数据目录
socket=/data/mysql/mysql.sock      # 指定套接字
symbolic-links=0                   # 数据只能存放到数据目录中,禁止链接到数据目录
server-id=33


6.# 数据库初始化建立mysql基本数据
[root@mysql-node3 ~]# mysql --user mysql --initialize    # 记得保存生成的初始化密码,在接下来的安全初始化需要用到
[root@mysql-node3 ~]# /etc/init.d/mysqld start           # 开启MySQL服务
[root@mysql-node3 ~]# chkconfig mysqld on                # 设置自启动
[root@mysql-node3 ~]# chkconfig --list                   # 查看自启动的服务

7.# 数据库安全初始化
[root@mysql-node3 ~]# mysql_secure_installation
2.4.2 从master中备份数据
# 从master节点备份数据
[root@mysql-nide1 ~]# mysqldump -uroot -p haha > haha.sql

注意:生产环境中备份时需要锁表,保证备份前后的数据一致

mysql> FLUSH TABLES WITH READ LOCK;

备份后再解锁

mysql> UNLOCK TABLES;

mysqldump命令备份的数据文件,在还原时先DROP TABLE,需要合并数据时需要删除此语句

--
-- Table structure for table `userlist`
--
DROP TABLE IF EXISTS `userlist`; #需要合并数据时需要删除此语句
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
# 将master的数据库备份发送到slave2中
[root@mysql-node1 ~]# scp /root/haha.sql root@172.25.254.33:/mnt
[root@mysql-node3 ~]# cd /mnt
[root@mysql-node3 mnt]# ls
haha.sql

# 利用master节点中备份出来的lee.sql在slave2中拉平数据
[root@mysql-node3 mnt]# mysql -uroot -p -e "create database haha;"   # 在slave2中创建haha数据库
[root@mysql-node3 mnt]# mysql -uroot -p haha < haha.sql    # 将备份的数据库放进haha数据库拉平数据
[root@mysql-node3 mnt]# mysql -uroot -p
mysql> select * from userlist;            # 查看数据是否拉平
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
+----------+----------+
1 row in set (0.01 sec)
2.4.3 配置slave2的slave功能
# 在master中查询日志pos
[root@mysql-node1 ~]# mysql -uroot -p -e "show master status;"
Enter password: 
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |     1244 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

# 在slave2中建立数据的从复制同步
mysql> use haha  # 登录到haha数据库
mysql> change master to master_host='172.25.254.13',master_user='repl',master_password='123123',master_log_file='mysql-bin.000001',master_log_pos=1244;          -- 设置从连接主库
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> start slave;       # 开启slave服务
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G   # 查看从库是否连接成功
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.25.254.13
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 1244
               Relay_Log_File: mysql-node3-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes  # I/O连接成功
            Slave_SQL_Running: Yes  # SQL连接成功
            . . . . . .
2.4.4 测试
1.# 在master中写入数据
[root@mysql-node1 ~]#  mysql -uroot -p -e "INSERT INTO haha.userlist VALUES('user2','222');"

2.# 在slave2中进行查看
mysql> select * from userlist;
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
| user2    | 222      |
+----------+----------+
2 rows in set (0.00 sec)

3.# 在slave1中进行查看
mysql> select * from haha.userlist;
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
| user2    | 222      |
+----------+----------+
2 rows in set (0.00 sec)

2.5 延迟恢复

  • 延迟复制时用来控制sql线程的,和i/o线程无关
  • 这个延迟复制不是i/o线程过段时间来复制,i/o是正常工作的
  • 是日志已经保存在slave端了,那个sql要等多久进行回放
  • 当master端误操作,可以在slave端进行数据备份
# 设置slave2来当作延迟数据库
mysql> stop slave sql_thread;             # 停止slave的SQL
Query OK, 0 rows affected (0.00 sec)

mysql> change master to master_delay=60;  # 修改主master的延迟
Query OK, 0 rows affected (0.00 sec)

mysql> start slave sql_thread;            # 重新开启slave的SQL
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G                # 查看延迟设定
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.25.254.13
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 1510
               Relay_Log_File: mysql-node3-relay-bin.000002
                Relay_Log_Pos: 586
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
			         . . .
                    SQL_Delay: 60          # 延迟60s
                       . . .

测试:

1.# 在master中模拟删除数据
mysql> use haha
mysql> delete from userlist where username='haha';    # 删除haha行的数据 
Query OK, 1 row affected (0.00 sec)

mysql> select * from userlist;  # 查看master的表数据
+----------+----------+
| username | password |
+----------+----------+
| user2    | 222      |
+----------+----------+
1 row in set (0.00 sec)


2.# 在slave2中60s前查看数据
mysql> select * from userlist;    
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
| user2    | 222      |
+----------+----------+
2 rows in set (0.00 sec)
[root@mysql-node3 ~]# mysqldump -uroot -p haha > haha.sql   # 有需求情况下对此时数据库进行备份

3.# 在slave2中60s后查看数据
mysql> select * from userlist;
+----------+----------+
| username | password |
+----------+----------+
| user2    | 222      |
+----------+----------+
1 row in set (0.00 sec)

4.# 数据恢复
[root@mysql-node3 ~]# scp /root/haha.sql root@172.25.254.13:/mnt

[root@mysql-nide1 mnt]# mysql -uroot -p haha < haha.sql
[root@mysql-nide1 mnt]# mysql -uroot -p -e "select * from haha.userlist;"    # 数据恢复
Enter password: 
+----------+----------+
| username | password |
+----------+----------+
| haha     | 123      |
| user2    | 222      |
+----------+----------+

2.6 慢查询日志

  • 慢查询,顾名思义,执行很慢的查询
  • 当执行SQL超过long_query_time参数设定的时间阈值(默认10s)时,就被认为是慢查询,这个SQL语句就是需要优化的
  • 慢查询被记录在慢查询日志里
  • 慢查询日志默认是不开启的
  • 如果需要优化SQL语句,就可以开启这个功能,它可以让你很容易地知道哪些语句是需要优化的。

慢查询日志在master端进行设置

# 查询慢查日志是否开启
mysql> show variables like "slow%";
+---------------------+----------------------------------+
| Variable_name       | Value                            |
+---------------------+----------------------------------+
| slow_launch_time    | 2                                |
| slow_query_log      | OFF                              |  # 慢查询日志默认关闭
| slow_query_log_file | /data/mysql/mysql-nide1-slow.log |
+---------------------+----------------------------------+
3 rows in set (0.01 sec)

# 开启慢查询日志
[root@mysql-nide1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=13
log-bin=mysql-bin
slow_query_log=ON; # 在客户端设置开机自启
[root@mysql-nide1 ~]# /etc/init.d/mysqld restart

[root@mysql-nide1 ~]# mysql -uroot -p

mysql> set global slow_query_log=ON;    # 在mysql中打开慢日志功能
Query OK, 0 rows affected (0.00 sec)

mysql> set long_query_time=4;           # 设置慢日志时间,默认10s
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "long%";     # 查看设置的慢查询时间
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 4.000000 |
+-----------------+----------+
1 row in set (0.01 sec)

mysql> show variables like "slow%";     
+---------------------+----------------------------------+
| Variable_name       | Value                            |
+---------------------+----------------------------------+
| slow_launch_time    | 2                                |
| slow_query_log      | ON                               |  # 已经开启慢日志功能
| slow_query_log_file | /data/mysql/mysql-nide1-slow.log |
+---------------------+----------------------------------+
3 rows in set (0.00 sec)

慢日志测试:

mysql> select sleep (10);   # 10s后执行命令
+------------+
| sleep (10) |
+------------+
|          0 |
+------------+
1 row in set (10.00 sec)

[root@mysql-node1 ~]# cat /data/mysql/mysql-node1-slow.log     # 查看慢查询日志
/usr/local/mysql/bin/mysqld, Version: 5.7.44-log (Source distribution). started with:
Tcp port: 3306  Unix socket: /data/mysql/mysql.sock
Time                 Id Command    Argument
# Time: 2024-08-25T03:36:32.234224Z
# User@Host: root[root] @ localhost []  Id:     2
# Query_time: 10.001551  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
use haha;
SET timestamp=1724556992;
select sleep (10);

2.7 MySQL的并行复制-多线程回放

1.查看slave中的线程信息

在这里插入图片描述

默认情况下slave中使用的是sql单线程回放

在master中时多用户读写,如果使用sql单线程回放那么会造成组从延迟严重

2.开启MySQL的多线程回放可以解决上述问题

# 在slave1中进行设置
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=23
super_read_only=on
gtid_mode=ON                       # 开启gtid
enforce-gtid-consistency=ON        # 设置保持gtid一致,不一致的舍弃

slave-parallel-type=LOGICAL_CLOCK  # 设置基于组提交
slave-parallel-workers=16          # 开启的线程数量
master_info_repository=TABLE       # master信息在表中记录,默认记在/data/mysql//master.info
relay_log_info_repository=TABLE    # 回放日志信息在表中记录,默认记录在/data/mysql/relay-log.info
relay_log_recovery=ON              # 日志回放恢复功能开启

[root@mysql-node2 ~]# /etc/init.d/mysqld restart

3.重新查看设置后的线程信息

在这里插入图片描述

此时sql线程转化为协调线程,16个worker负责处理sql协调线程发送过来的处理请求

MySQL 组提交(Group commit)是一个性能优化特性,它允许在一个事务日志同步操作中将多个事务的日志记录一起写入。这样做可以减少磁盘I/O的次数,从而提高数据库的整体性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C语言】深入理解指针(四)qsort函数的实现

指针4 1.回调函数是什么2.qsort使用举例3.qsort函数的模拟实现 1.回调函数是什么 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#xff0c;被调⽤的…

【CanMV K230】外接传感器

【CanMV K230】外接传感器 外接LED灯 B站视频链接 抖音链接 我们后面主要做是机器视觉。K230能帮我们捕捉到图像信息。更多小功能需要我们自己来做。 比如舵机抬杆&#xff0c;测温报警等 都需要我们外接传感器。 本篇就来分享一下如何使用K230外接传感器 首先需要知道K230…

Leetcode JAVA刷刷站(98)验证二叉搜索树

一、题目概述 二、思路方向 在Java中&#xff0c;要判断一个二叉树是否是有效的二叉搜索树&#xff08;BST&#xff09;&#xff0c;我们可以采用递归的方法&#xff0c;通过维护一个外部的范围&#xff08;通常是Integer.MIN_VALUE到Integer.MAX_VALUE作为初始范围&#xff…

网络优化4|网络流问题|路径规划问题|车辆路径问题

网络流问题 网络最大流问题 研究网络通过的流量也是生产管理中经常遇到的问题 例如&#xff1a;交通干线车辆最大通行能力、生产流水线产品最大加工能力、供水网络中最大水流量等。这类网络的弧有确定的容量&#xff0c;虽然常用 c i j c_{ij} cij​表示从节点 i i i到节点 j…

怎么检测电脑的RAM?丨什么是RAM?

RAM 是 Random Access Memory 的缩写&#xff0c;它是一个允许计算机短期存储数据以更快访问的组件。众所周知&#xff0c;操作系统、应用程序和各种个人文件都存储在硬盘驱动器中。 当 CPU 需要调用硬盘上的数据进行计算和运行时&#xff0c;CPU 会将数据传输到 RAM 中进行计…

安防视频汇聚平台EasyCVR启动后无法访问登录页面是什么原因?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台基于云边端一体化架构&#xff0c;兼容性强、支持多协议接入&#xff0c;包括国标GB/T28181协议、部标JT808、GA/T1400协议、RTMP、RTSP/Onvif协议、海康Ehome、海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石云SDK等…

科研绘图系列:R语言多组极坐标图(grouped polar plot)

介绍 Polar plot(极坐标图)是一种二维图表,它使用极坐标系统来表示数据,而不是像笛卡尔坐标系(直角坐标系)那样使用x和y坐标。在极坐标图中,每个数据点由一个角度(极角)和一个半径(极径)来确定。角度通常从水平线(或图表的某个固定参考方向)开始测量,而半径则是…

Jenkins发邮件功能如何配置以实现自动化?

jenkins发邮件的设置指南&#xff1f;Jenkins怎么配置服务器&#xff1f; Jenkins作为一个流行的自动化服务器&#xff0c;其发邮件功能是通知团队成员构建状态的重要手段。AokSend将详细介绍如何配置Jenkins发邮件功能&#xff0c;以实现自动化通知。 Jenkins发邮件&#xf…

NVI技术创新联盟成立,BOSMA博冠IP轻量化制播已运用

2024年北京国际广播电影电视展览会&#xff08;BIRTV&#xff09;首日&#xff0c;由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV 2024超高清全产业链发展研讨会上宣布正式成立。作为国产8K摄像机先行者&#xff0c;BOSMA博冠受邀加入NVI技术…

Flowable BPMN bpmnjs 设计器

最近半年我一直在打造一款行业顶尖的流程设计器&#xff0c;适配了flowable所有的组件&#xff0c;美观&#xff0c;大方&#xff0c;灵活&#xff0c;好用。所有的组件都进行严格的测试并在生产环境上线了。 1、在线预览 2、整体框架布局 3、组件分组 4、完整模式切换 给大…

若依,前后端分离项目,部署到服务器

1.后端项目用maven打包 正式服的话&#xff0c;测试不用加。 application.yml加上context-path: /prod-api 一定要选择root的ruoyi&#xff0c;他会把你自动打包其他模块的依赖 全部成功。然后去ruoyi-admin拿到这个包&#xff0c;java -jar ruoyi-admin.jar就可以了 将jar上…

STM32嵌套向量中断控制器—NVIC

NVIC简介&#xff1a; NVIC&#xff0c;即Nested Vectored Interrupt Controller&#xff08;嵌套向量中断控制器&#xff09;&#xff0c;是STM32中的中断控制器。它负责管理和协调处理器的中断请求&#xff0c;是STM32中处理异步事件的重要机制。 NVIC提供了灵活、高效、可扩…

IoTDB 在顶级会议 VLDB 2024:四篇最新论文入选,特邀做 TPC 报告与讨论会!

再获权威顶会认可 8 月 26 日至 8 月 30 日&#xff0c;数据库领域的顶级国际会议 VLDB 2024 在广州举行。IoTDB 三篇论文的最新研发成果被本次大会录用&#xff0c;这其中也包括 TsFile 成为 Apache Top-Level 项目后发表的第一篇顶会论文。 同时&#xff0c;在国际权威数据库…

博弈论详解 2(SG函数 和 SG定理)

传送门&#xff1a;博弈论详解 1&#xff08;基本理论定义 和 Nim 游戏&#xff09; 什么是 SG 函数 接着上次的讲解&#xff0c;我们来了解一个更通用的模型。我们把每一个状态变成一个点&#xff08;在 Nim 游戏里就代表 a a a 数组&#xff09;&#xff0c;如果可以从一种…

008、架构_分布式事务

分布式事务控制 对于一个分布式写事务,计算节点会向GTM申请全局事务GTID,GTID申请成功后,称当前GTID对应的事务是活跃事务,处于未提交状态。如果涉及数据更新,则将GTID信息同步更新到该事务要更新的事务中。成功提交事务后,这里的成功是指分布式事务涉及所有数据节点均提…

C++入门基础知识37——【关于C++ 运算符——关系运算符】

成长路上不孤单&#x1f60a;【14后&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

Day24 第11站 出发 c++!

1> 思维导图 2> 提示并输入一个字符串&#xff0c;统计该字符串中字母个数、数字个数、空格个数、其他字符的个数 string s1;cout << "请输入一个字符串" << endl;getline(cin,s1);int len s1.length();char buf[128]"";strcpy(buf,s1…

如何使用Smart-Doc高效生成Java WebSocket接口文档

前言 Smart-Doc 是一款强大的文档生成工具&#xff0c;可以帮助开发者轻松地为Java 项目生成清晰、详细的 API 文档。随着WebSocket技术的普及&#xff0c;Smart-Doc 在3.0.7版本开始也增加了对 WebSocket 接口的支持。本文将详细介绍如何使用 Smart-Doc 生成 Java WebSocket …

DIY 300以上fps游戏 台式机 2024年8月(cpu)

组装台式机 CPU处理器 前言&#xff1a;因特尔霸榜&#xff0c;目前cpu全部都是国外产&#xff0c;锐龙是国外在中国的代理。 2024双十一cpu销量 首推cpu&#xff1a;性价比第三名 Intel 酷睿i5 12600KF 1149元 &#xff08;瓦死斗帧率在200-400之间&#xff0c;300上下浮动…

浅谈SpringMvc的核心流程与组件

一、SpringMvc的核心流程 当发起请求时被前置的控制器(DispatcherServlet)拦截到请求&#xff0c;根据请求参数生成代理请求&#xff0c;找到请求对应的实际控制器&#xff0c;控制器处理请求&#xff0c;创建数据模型&#xff0c;访问数据库&#xff0c;将模型响应给中心控制…