MySQL InnoDB Replication部署方案与实践

1. 概述

MySQL Innodb ReplicaSet 是 MySQL 团队在 2020 年推出的一款产品,用来帮助用户快速部署和管理主从复制,在数据库层仍然使用的是主从复制技术。

ReplicaSet 主要包含三个组件:MySQL Router、MySQL Server 以及 MySQL Shell 高级客户端。

MySQL Shell 负责管理 ReplicaSet 包括部署、切换、节点加入等,都可以通过内置 AdminAPI 自动化完成。

MySQL Router 是一款轻量级中间件,可在应用程序和 ReplicaSet 之间提供透明路由和读写分离功能。

2. 适用场景

InnoDB ReplicaSet至少由两台MySQL服务器实例组成,提供MySQL主从复制功能。InnoDB ReplicaSet基于异步的主从复制实现,因此适用于用户对高可用性要求不高的环境。可以通过MySQL Shell快速搭建及管理主从复制,避免了搭建主从复制时大量的手动操作。

InnoDB ReplicaSet的不足之处有:

  • 不支持自动故障转移。主库不可用时,需要通过AdminAPI手动发起故障转移。

  • 发生计划外的服务不可用时,可能会丢失部分数据。由于主备之间是异步复制,主库发生故障时,未提交的事务会丢失。

  • 发生计划外的服务不可用时,可能会产生数据不一致。例如由于网络原因导致主库连不上,将备库提升为主库后,可能会同时存在两个主库,即发生“脑裂”。

  • 不支持多主模式,即同一时刻只有一个主库可写。

  • 读扩展受限,不能像组复制那样对流量进行控制。

  • 所有的备库都从同一个主库复制数据。在有大量的小更新时,可能会对主库造成影响。

  • 仅支持MySQL 8.0及其以后的版本。

  • 仅支持基于GTID的日志复制。

  • 仅支持基于行的日志复制(Row-Based Replication, RBR),不支持基于SQL语句的复制(Statement-Based Replication, SBR)。

  • 不支持复制过滤。

  • RS为一个主库加多个从库的架构。需要通过MySQL Router监视RS中的实例,因此从库的数量不能无限制增加。

  • 必须通过MySQL Shell配置和管理,包括复制用户的创建。

3. 安装部署

IProlehostname版本OS
192.168.10.31Mastermysql-rs-1MySQL 8.2Centos_7.9_x86_x64
192.168.10.32Secondarymysql-rs-2MySQL 8.2Centos_7.9_x86_x64

3.1. 安装MySQL servers

分别在两个MySQL服务器下载MySQL Server安装包,并进行安装。

# 配置主机名
echo "192.168.10.31   mysql-rs-1" >> /etc/hosts
echo "192.168.10.32   mysql-rs-2" >> /etc/hosts
​
# 192.168.10.31执行
hostnamectl set-hostname mysql-rs-1
bash
# 192.168.10.32执行
hostnamectl set-hostname mysql-rs-2
bash
# 下载rpm安装包
wget https://cdn.mysql.com//Downloads/MySQL-8.2/mysql-8.2.0-1.el7.x86_64.rpm-bundle.tar
​
# 解压
tar -xvf mysql-8.2.0-1.el7.x86_64.rpm-bundle.tar
​
# 卸载mariadb
rpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps
​
# 安装MySQL
yum localinstall -y *.rpm

分别配置root密码:

[root@mysql-rs-2 server]# mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.2.0
​
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> 
mysql> 
mysql> alter user root@'localhost' identified by 'Abcd@1234';
Query OK, 0 rows affected (0.00 sec)
​
mysql> create user root@'%' identified by 'Abcd@1234';
Query OK, 0 rows affected (0.01 sec)

3.2. 安装mysqlsh

# 下载mysqlshell
wget https://cdn.mysql.com//Downloads/MySQL-Shell/mysql-shell-8.2.0-1.el7.x86_64.rpm
# 安装mysqlshell
rpm -ivh mysql-shell-8.2.0-1.el7.x86_64.rpm

验证mysql shell链接数据库

[root@mysql-rs-1 software]# mysqlsh --mysql -u root -h localhost -C
Please provide the password for 'root@localhost': ************
Save password for 'root@localhost'? [Y]es/[N]o/Ne[v]er (default No): 
Error during auto-completion cache update: You must reset your password using ALTER USER statement before executing this statement.
MySQL Shell 8.2.0
​
Copyright (c) 2016, 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 '\?' for help; '\quit' to exit.
Creating a Classic session to 'root@localhost?compression=REQUIRED'
Your MySQL connection id is 8
No default schema selected; type \use <schema> to set one.
 MySQL  localhost  JS > 

3.3. 配置实例

在其中一个主机上启动mysqlsh连接

[root@mysql-rs-1 software]# mysqlsh root@mysql-rs-1:3306
MySQL Shell 8.2.0
​
Copyright (c) 2016, 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 '\?' for help; '\quit' to exit.
Creating a session to 'root@mysql-rs-1:3306'
Fetching schema names for auto-completion... Press ^C to stop.
Your MySQL connection id is 21
Server version: 8.2.0 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.

分别给root用户授权:

GRANT CLONE_ADMIN, CONNECTION_ADMIN, CREATE USER, EXECUTE, FILE, GROUP_REPLICATION_ADMIN, PERSIST_RO_VARIABLES_ADMIN, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, REPLICATION_APPLIER, REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SELECT, SHUTDOWN, SYSTEM_VARIABLES_ADMIN ON *.* TO 'root'@'%' WITH GRANT OPTION;
GRANT DELETE, INSERT, UPDATE ON mysql.* TO 'root'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata.* TO 'root'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata_bkp.* TO 'root'@'%' WITH GRANT OPTION;
GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE ON mysql_innodb_cluster_metadata_previous.* TO 'root'@'%' WITH GRANT OPTION;

在MySQL Shell中执行:

配置mysql-rs-1:

 MySQL  mysql-rs-1:3306 ssl  JS > dba.configureReplicaSetInstance('root@mysql-rs-1:3306', {clusterAdmin: "rs_admin"})
Configuring local MySQL instance listening at port 3306 for use in an InnoDB ReplicaSet...
​
This instance reports its own address as mysql-rs-1:3306
Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.
Assuming full account name 'rs_admin'@'%' for rs_admin
Password for new account: *********
Confirm password: *********
​
applierWorkerThreads will be set to the default value of 4.
​
NOTE: Some configuration options need to be fixed:
+----------------------------------------+---------------+----------------+--------------------------------------------------+
| Variable                               | Current Value | Required Value | Note                                             |
+----------------------------------------+---------------+----------------+--------------------------------------------------+
| binlog_transaction_dependency_tracking | COMMIT_ORDER  | WRITESET       | Update the server variable                       |
| enforce_gtid_consistency               | OFF           | ON             | Update read-only variable and restart the server |
| gtid_mode                              | OFF           | ON             | Update read-only variable and restart the server |
| server_id                              | 1             | <unique ID>    | Update read-only variable and restart the server |
+----------------------------------------+---------------+----------------+--------------------------------------------------+
​
Some variables need to be changed, but cannot be done dynamically on the server.
Do you want to perform the required configuration changes? [y/n]: y
Do you want to restart the instance after configuring it? [y/n]: y
​
Creating user rs_admin@%.
Account rs_admin@% was successfully created.
​
Configuring instance...
​
WARNING: '@@binlog_transaction_dependency_tracking' is deprecated and will be removed in a future release. (Code 1287).
The instance 'mysql-rs-1:3306' was configured to be used in an InnoDB ReplicaSet.
Restarting MySQL...
NOTE: MySQL server at mysql-rs-1:3306 was restarted.

配置mysql-rs-2:

 MySQL  mysql-rs-1:3306 ssl  JS > dba.configureReplicaSetInstance('root@mysql-rs-2:3306', {clusterAdmin: "rs_admin"})
Please provide the password for 'root@mysql-rs-2:3306': *********
Save password for 'root@mysql-rs-2:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
Configuring MySQL instance at mysql-rs-2:3306 for use in an InnoDB ReplicaSet...
​
This instance reports its own address as mysql-rs-2:3306
Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.
Assuming full account name 'rs_admin'@'%' for rs_admin
Password for new account: *********
Confirm password: *********
​
applierWorkerThreads will be set to the default value of 4.
​
NOTE: Some configuration options need to be fixed:
+----------------------------------------+---------------+----------------+--------------------------------------------------+
| Variable                               | Current Value | Required Value | Note                                             |
+----------------------------------------+---------------+----------------+--------------------------------------------------+
| binlog_transaction_dependency_tracking | COMMIT_ORDER  | WRITESET       | Update the server variable                       |
| enforce_gtid_consistency               | OFF           | ON             | Update read-only variable and restart the server |
| gtid_mode                              | OFF           | ON             | Update read-only variable and restart the server |
| server_id                              | 1             | <unique ID>    | Update read-only variable and restart the server |
+----------------------------------------+---------------+----------------+--------------------------------------------------+
​
Some variables need to be changed, but cannot be done dynamically on the server.
Do you want to perform the required configuration changes? [y/n]: y
Do you want to restart the instance after configuring it? [y/n]: y
​
Creating user rs_admin@%.
Account rs_admin@% was successfully created.
​
Configuring instance...
​
WARNING: '@@binlog_transaction_dependency_tracking' is deprecated and will be removed in a future release. (Code 1287).
The instance 'mysql-rs-2:3306' was configured to be used in an InnoDB ReplicaSet.
Restarting MySQL...
NOTE: MySQL server at mysql-rs-2:3306 was restarted.

3.4. 创建ReplicationSet

创建ReplicationSet,默认会将当前进入的实例为主库实例:

 MySQL  mysql-rs-1:3306 ssl  JS > dba.createReplicaSet('ReplicaSet')
A new replicaset with instance 'mysql-rs-1:3306' will be created.
​
* Checking MySQL instance at mysql-rs-1:3306
​
This instance reports its own address as mysql-rs-1:3306
mysql-rs-1:3306: Instance configuration is suitable.
​
* Checking connectivity and SSL configuration...
* Updating metadata...
​
ReplicaSet object successfully created for mysql-rs-1:3306.
Use rs.addInstance() to add more asynchronously replicated instances to this replicaset and rs.status() to check its status.
​
<ReplicaSet:ReplicaSet> 

3.5. 将另一个实例加入到创建的 ReplicaSet

 MySQL  mysql-rs-1:3306 ssl  JS > var rs = dba.getReplicaSet()
 You are connected to a member of replicaset 'ReplicaSet'.
 
 MySQL  mysql-rs-1:3306 ssl  JS > rs.addInstance('mysql-rs-2:3306')
Adding instance to the replicaset...
​
* Performing validation checks
​
This instance reports its own address as mysql-rs-2:3306
mysql-rs-2:3306: Instance configuration is suitable.
​
* Checking async replication topology...
​
* Checking connectivity and SSL configuration...
​
* Checking transaction state of the instance...
​
NOTE: The target instance 'mysql-rs-2:3306' has not been pre-provisioned (GTID set is empty). The Shell is unable to decide whether replication can completely recover its state.
The safest and most convenient way to provision a new instance is through automatic clone provisioning, which will completely overwrite the state of 'mysql-rs-2:3306' with a physical snapshot from an existing replicaset member. To use this method by default, set the 'recoveryMethod' option to 'clone'.
​
WARNING: It should be safe to rely on replication to incrementally recover the state of the new instance if you are sure all updates ever executed in the replicaset were done with GTIDs enabled, there are no purged transactions and the new instance contains the same GTID set as the replicaset or a subset of it. To use this method by default, set the 'recoveryMethod' option to 'incremental'.
​
​
Please select a recovery method [C]lone/[I]ncremental recovery/[A]bort (default Clone): 
* Updating topology
Monitoring Clone based state recovery of the new member. Press ^C to abort the operation.
Clone based state recovery is now in progress.
​
NOTE: A server restart is expected to happen as part of the clone process. If the
server does not support the RESTART command or does not come back after a
while, you may need to manually start it back.
​
* Waiting for clone to finish...
NOTE: mysql-rs-2:3306 is being cloned from mysql-rs-1:3306
** Stage DROP DATA: Completed
** Clone Transfer  
    FILE COPY  ############################################################  100%  Completed
    PAGE COPY  ############################################################  100%  Completed
    REDO COPY  ############################################################  100%  Completed
* Clone process has finished: 76.80 MB transferred in about 1 second (~76.80 MB/s)
​
** Changing replication source of mysql-rs-2:3306 to mysql-rs-1:3306
** Waiting for new instance to synchronize with PRIMARY...
** Transactions replicated  ############################################################  100% 
​
The instance 'mysql-rs-2:3306' was added to the replicaset and is replicating from mysql-rs-1:3306.
​
* Waiting for instance 'mysql-rs-2:3306' to synchronize the Metadata updates with the PRIMARY...
** Transactions replicated  ############################################################  100% 

3.6. 查看副本集状态

 MySQL  mysql-rs-1:3306 ssl  JS > var rs = dba.getReplicaSet()
You are connected to a member of replicaset 'ReplicaSet'.
 MySQL  mysql-rs-1:3306 ssl  JS > rs.status()
{
    "replicaSet": {
        "name": "ReplicaSet", 
        "primary": "mysql-rs-1:3306", 
        "status": "AVAILABLE", 
        "statusText": "All instances available.", 
        "topology": {
            "mysql-rs-1:3306": {
                "address": "mysql-rs-1:3306", 
                "instanceRole": "PRIMARY", 
                "mode": "R/W", 
                "status": "ONLINE"
            }, 
            "mysql-rs-2:3306": {
                "address": "mysql-rs-2:3306", 
                "instanceRole": "SECONDARY", 
                "mode": "R/O", 
                "replication": {
                    "applierStatus": "APPLIED_ALL", 
                    "applierThreadState": "Waiting for an event from Coordinator", 
                    "applierWorkerThreads": 4, 
                    "receiverStatus": "ON", 
                    "receiverThreadState": "Waiting for source to send event", 
                    "replicationLag": null, 
                    "replicationSsl": "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2", 
                    "replicationSslMode": "REQUIRED"
                }, 
                "status": "ONLINE"
            }
        }, 
        "type": "ASYNC"
    }
}

3.7. 配置MySQL Router

# 下载MySQL Router
wget https://cdn.mysql.com//Downloads/MySQL-Router/mysql-router-community-8.2.0-1.el7.x86_64.rpm
# 安装
rpm -ivh mysql-router-community-8.2.0-1.el7.x86_64.rpm
 MySQL  mysql-rs-1:3306 ssl  JS > var rs = dba.getReplicaSet()
You are connected to a member of replicaset 'ReplicaSet'.
 MySQL  mysql-rs-1:3306 ssl  JS > rs.setupRouterAccount('rs_router1')
​
Missing the password for new account rs_router1@%. Please provide one.
Password for new account: *********
Confirm password: *********
​
​
Creating user rs_router1@%.
Account rs_router1@% was successfully created.

3.8. 引导启动MySQL Router

[root@mysql-rs-1 software]# mysqlrouter --bootstrap root@mysql-rs-1:3306 --user mysqlrouter
Please enter MySQL password for root: 
# Bootstrapping system MySQL Router 8.2.0 (MySQL Community - GPL) instance...
​
- Creating account(s) (only those that are needed, if any)
- Verifying account (using it to run SQL queries that would be run by Router)
- Storing account in keyring
- Adjusting permissions of generated files
- Creating configuration /etc/mysqlrouter/mysqlrouter.conf
​
Existing configuration backed up to '/etc/mysqlrouter/mysqlrouter.conf.bak'
​
# MySQL Router configured for the InnoDB ReplicaSet 'ReplicaSet'
​
After this MySQL Router has been started with the generated configuration
​
    $ /etc/init.d/mysqlrouter restart
or
    $ systemctl start mysqlrouter
or
    $ mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf
​
InnoDB ReplicaSet 'ReplicaSet' can be reached by connecting to:
​
## MySQL Classic protocol
​
- Read/Write Connections: localhost:6446
- Read/Only Connections:  localhost:6447
- Read/Write Split Connections: localhost:6450
​
## MySQL X protocol
​
- Read/Write Connections: localhost:6448
- Read/Only Connections:  localhost:6449

3.9. 读写分离验证

检查ReplicaSet,可以看到主节点(读写)为mysql-rs-1:3306,从节点(只读)为mysql-rs-2:3306

 MySQL  mysql-rs-1:3306 ssl  JS > rs.status()
{
    "replicaSet": {
        "name": "ReplicaSet", 
        "primary": "mysql-rs-1:3306", 
        "status": "AVAILABLE", 
        "statusText": "All instances available.", 
        "topology": {
            "mysql-rs-1:3306": {
                "address": "mysql-rs-1:3306", 
                "instanceRole": "PRIMARY", 
                "mode": "R/W", 
                "status": "ONLINE"
            }, 
            "mysql-rs-2:3306": {
                "address": "mysql-rs-2:3306", 
                "instanceRole": "SECONDARY", 
                "mode": "R/O", 
                "replication": {
                    "applierStatus": "APPLIED_ALL", 
                    "applierThreadState": "Waiting for an event from Coordinator", 
                    "applierWorkerThreads": 4, 
                    "receiverStatus": "ON", 
                    "receiverThreadState": "Waiting for source to send event", 
                    "replicationLag": null, 
                    "replicationSsl": "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2", 
                    "replicationSslMode": "REQUIRED"
                }, 
                "status": "ONLINE"
            }
        }, 
        "type": "ASYNC"
    }
}

检查mysqlrouter,可以看到MySQL Router读写端口为6450

 MySQL  mysql-rs-1:3306 ssl  JS > rs.listRouters()
{
    "replicaSetName": "ReplicaSet", 
    "routers": {
        "mysql-rs-1::system": {
            "hostname": "mysql-rs-1", 
            "lastCheckIn": "2023-11-14 11:40:21", 
            "roPort": "6447", 
            "roXPort": "6449", 
            "rwPort": "6446", 
            "rwSplitPort": "6450", 
            "rwXPort": "6448", 
            "version": "8.2.0"
        }
    }
}

下面通过MySQL Router的读写端口6450连接mysql数据库:

[root@mysql-rs-1 ~]# mysqlsh mysql://root@mysql-rs-1:6450 --sql
MySQL Shell 8.2.0
​
Copyright (c) 2016, 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 '\?' for help; '\quit' to exit.
Creating a Classic session to 'root@mysql-rs-1:6450'
Fetching global names for auto-completion... Press ^C to stop.
Your MySQL connection id is 0
Server version: 8.2.0 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
 MySQL  mysql-rs-1:6450 ssl  SQL > 

查询数据,发现当前节点为从节点:

 MySQL  mysql-rs-1:6450 ssl  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-2 |   3306 |
+------------+--------+
1 row in set (0.0035 sec)
Statement ID: 13700

开启事务,会自动切换到主节点:

 MySQL  mysql-rs-1:6450 ssl  SQL > start transaction;
Query OK, 0 rows affected (0.0031 sec)
Statement ID: 20477
 MySQL  mysql-rs-1:6450 ssl  ★  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-1 |   3306 |
+------------+--------+
1 row in set (0.0007 sec)
Statement ID: 20563

提交或者回滚事务后,自动切换到从节点:

 MySQL  mysql-rs-1:6450 ssl  ★  SQL > rollback;
Query OK, 0 rows affected (0.0006 sec)
Statement ID: 21909
 MySQL  mysql-rs-1:6450 ssl  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-2 |   3306 |
+------------+--------+
1 row in set (0.0020 sec)
Statement ID: 15489

只读事务中,也会切换到从节点:

 MySQL  mysql-rs-1:6450 ssl  SQL > start transaction read only;
Query OK, 0 rows affected (0.0029 sec)
Statement ID: 16970
 MySQL  mysql-rs-1:6450 ssl  ☆  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-2 |   3306 |
+------------+--------+
1 row in set (0.0010 sec)
Statement ID: 16996

用户还可以在会话中使用ROUTER SET access_mode=命令来定义应用要连接的实例类型:

 MySQL  mysql-rs-1:6450 ssl  SQL > router set access_mode='read_write';
Query OK, 0 rows affected (0.0004 sec)
 MySQL  mysql-rs-1:6450 ssl  -  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-1 |   3306 |
+------------+--------+
1 row in set (0.0017 sec)
Statement ID: 25535
 MySQL  mysql-rs-1:6450 ssl  SQL > router set access_mode='read_only';
Query OK, 0 rows affected (0.0006 sec)
 MySQL  mysql-rs-1:6450 ssl  -  SQL > select @@hostname, @@port;
+------------+--------+
| @@hostname | @@port |
+------------+--------+
| mysql-rs-2 |   3306 |
+------------+--------+
1 row in set (0.0043 sec)
Statement ID: 18508

4. 总结

总之,MySQL Router 8.2支持读写分离。这是一项有价值的功能,可以优化数据库性能和可扩展性,而无需在应用程序中进行任何更改。这种配置使您能够将所有读流量引导到只读实例,将所有写流量引导到读写实例。这不仅增强了用户的整体体验,还简化了数据库管理和部署。

读写实例是主实例或源实例。只读实例是副本(InnoDB集群的非主实例、ReplicaSet的非主实例或复制集群中的非主实例)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在线课堂知识付费小程序源码系统 开发组合PHP+MySQL:用手机随时随地地学习,讲师亲自在线授业解惑 带安装部署教程

近年来&#xff0c;人们对于学习的需求也日益增加。传统的课堂教学已经无法满足人们的学习需求&#xff0c;而在线课堂则能够让人们随时随地地进行学习。同时&#xff0c;随着知识付费的兴起&#xff0c;越来越多的讲师也愿意将自己的知识和经验分享给更多的人。因此&#xff0…

温湿度传感器DHT11的简单应用

文章目录 一、DHT11是什么&#xff1f;二、使用步骤1.硬件1.硬件连接2.工作原理1.串行单总线2.温湿度数据采集原理 2.软件1.DHT11初始化如下&#xff08;示例&#xff09;&#xff1a;2.DHT11复位如下&#xff08;示例&#xff09;&#xff1a;3.等待DHT11的回应如下&#xff0…

@Transactional失效问题

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 关于Transactional 日…

酷开科技多维度赋能营销,实力斩获三项大奖

在数智化新阶段、广告新生态、传播新业态的背景下&#xff0c;“第30届中国国际广告节广告主盛典暨网易传媒态度营销峰会”于11月18日在厦门国际会展中心盛大举行。来自全国的品牌方、战略决策者、媒体平台和品牌服务机构等汇聚一堂。在50000&#xff0b;现场观众和数千万线上观…

SSL证书HTTPS保护服务

SSL证书属于数字证书的其中一种&#xff0c;广泛用于https协议&#xff0c;从而可以让数据传输在加密前提下完成&#xff0c;确保HTTPS网络安全是申请SSL证书必要工作。 SSL证书是主要用于https是一种加密协议&#xff0c;仔细观察网站地址会发现目前主流的网址前面都会有http…

Linux操作系统学习(零)、计算机概论

计算机概论 指令集 CPU中含有多种指令集&#xff0c;指令集对于CPU运算具有指导和优化的硬程序&#xff0c;用来引导CPU进行加减运算和控制计算机操作系统的一系列指令的集合 常见的就有微指令集RISC和复杂指令集CISC RISC&#xff1a;包括ARM架构和PPC架构 CISC&#xff…

HTML面试题---专题四

文章目录 一、前言二、如何在 HTML 中嵌入音频文件&#xff1f;三、解释 <script> 标签中 defer 属性的用途。四、如何在 HTML 中创建粘性/固定导航栏&#xff1f;五、HTML 中的 span 元素的用途是什么&#xff1f;六、如何使 HTML 元素可拖动&#xff1f;七、解释 <i…

项目中使用Arrays.asList、ArrayList.subList的坑

使用Arrays.asList的注意事项 1.1 可能会踩的坑 先来看下Arrays.asList的使用&#xff1a; List<Integer> statusList Arrays.asList(1, 2); System.out.println(statusList); System.out.println(statusList.contains(1)); System.out.println(statusList.contains(3)…

如何打造稳健高效的数据库的基础设施?数据库云提出创新方案

引言 数据库的云化、丰富业务场景下多元的数据库类型、公有云与私有云交织的IT架构&#xff0c;叠加信创影响使得企业内部的基础设施日益复杂&#xff0c;如何高效管理多元的数据库和多云异构基础设施正成为企业面临的严峻挑战。 在此背景下&#xff0c;数据库云应运而生。数…

六级翻译之印章

好像大房子挺难得 三段式 1Since ancient from now&#xff0c;seals have been a symbol of power and certerfiction of identity.seals not only practical but also is a form of art.Seal is an ancient art combining with manafutuer of crafting and desgin of…

界面控件DevExpress中文教程 - 如何用Office File API组件填充PDF表单

DevExpress Office File API是一个专为C#, VB.NET 和 ASP.NET等开发人员提供的非可视化.NET库。有了这个库&#xff0c;不用安装Microsoft Office&#xff0c;就可以完全自动处理Excel、Word等文档。开发人员使用一个非常易于操作的API就可以生成XLS, XLSx, DOC, DOCx, RTF, CS…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion替换背景

在Stable Diffusion软件中,使用ControlNet+模型实现固定物体批量替换背景 出图的流程。 一、准备好图片 1.你需要准备好一些白底图或者透明底图用于训练模型。 2.你需要准备同样角度的其他背景色底图用于ControlNet勾线 3.注意检查你的图片尺寸,是否为1:1,…

安防 音响 车载等产品中音频接口选型的高性能国产芯片分析

在人工智能兴起之后&#xff0c;安防市场就成为了其全球最大的市场&#xff0c;也是成功落地的最主要场景之一。对于安防应用而言&#xff0c;智慧摄像头、智慧交通、智慧城市等概念的不断涌现&#xff0c;对于芯片产业催生出海量需求。今天&#xff0c;我将为大家梳理GLOBALCH…

STM32 CAN多节点组网项目实操 挖坑与填坑记录

摘要 CAN线性组网项目开发过程中遇到的数据丢包问题&#xff0c;并尝试解决的记录和推测分析。 关键词 CAN串联多节点通讯、CAN10节点通讯、CAN数据丢包、STM32 CAN 背景/项目介绍 概述&#xff1a; 开发了一个多节点线性组网采集数据的项目。 系统包含1个供电和数据网关板还有…

mysql:查看一个表的索引信息

可以使用命令SHOW INDEX FROM table_name;查看一个表的索引信息&#xff0c;例如&#xff1a;

NGROK内网穿透工具-实战+源码下载

1、功能概述&#xff1f; 本案例中使用ngrok内网穿透工具&#xff0c;使用方便&#xff0c;不需要注册等麻烦的操作&#xff0c;永久使用&#xff0c;一键搞定。 我们在项目中有这样一种需求&#xff1a; 甲方&#xff1a;汤工你能不能把你们正在开发的项目或者页面发给我看…

vue脚手架创建项目

安装 npm install -g vue/cli 如果报错可以尝试使用cnpm 查看命令 vue -V 创建项目 vue create 项目名称 输入y 上下选中选项 Manually select features &#xff08;自由选择&#xff09;&#xff0c;回车 vue 版本的选择 其他按需要选择 项目创建成功&#xff0c;…

C++基础知识

目录 前言&#xff1a; 命名空间 命名空间的定义 命名空间的使用 c输入与输出 缺省参数 函数重载 引用 引用的特性 常引用 引用的使用场景 引用做参数 引用做返回值 引用与指针的区别 内联函数 内联函数的特性 前言&#xff1a; C 语言是结构化和模块化的语言&…

服务器数据恢复—raid5少盘状态下新建raid5如何恢复原raid5数据?

服务器数据恢复环境&#xff1a; 一台服务器上搭建了一组由5块硬盘组建的raid5阵列&#xff0c;服务器上层存放单位重要数据&#xff0c;无备份文件。 服务器故障&分析&#xff1a; 服务器上raid5有一块硬盘掉线&#xff0c;外聘运维人员在没有了解服务器具体情况下&#x…

【教程】制作 iOS 推送证书

​ 目录 证书类型 MAC Key Store 消息推送控制台 制作证书 创建苹果 App ID 使用appuploder制作 .p12文件 创建证书 如需向 iOS 设备推送数据&#xff0c;您首先需要在消息推送控制台上配置 iOS 推送证书。iOS 推送证书用于推送通知&#xff0c;本文将介绍消息推送服务支…