news 2026/1/5 9:34:54

什么是读写分离?如何实现?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
什么是读写分离?如何实现?

本报告旨在全面、深入地探讨数据库读写分离(Read-Write Separation)技术。读写分离作为一种关键的数据库架构优化模式,通过将数据库的读操作与写操作分流至不同的服务器实例,极大地提升了现代应用系统的性能、可用性和可扩展性。

报告首先从读写分离的核心概念入手,阐述了其基本原理、适用场景、主要优势(如性能提升、高可用性)以及固有的挑战(如数据一致性、架构复杂性)。随后,报告系统性地梳理了读写分离的三种主要实现层次:应用层代码实现、中间件代理实现以及数据库原生方案,并对它们的优缺点进行了比较分析。

报告的核心部分详细剖析了当前业界主流关系型数据库——MySQL 和 PostgreSQL——的多种读写分离实现方案。针对MySQL,报告深入研究了“原生复制+ProxySQL”、“MySQL InnoDB Cluster”官方方案、基于 GTID 的高级复制技术,以及面向云原生时代的分布式解决方案 “Vitess”。针对PostgreSQL,报告重点阐述了利用强大中间件 “pgpool-II” 结合原生复制(流复制与逻辑复制)的实现方法。每个方案都包含了详尽的架构解析、分步配置指南、关键参数说明和常见问题规避策略。

随着云计算和容器化技术的普及,本报告进一步将视野拓展至云环境与 Kubernetes 环境下的读写分离。报告分析了 AWS、阿里云、Google Cloud 等主流云服务商提供的托管式读写分离服务(如 AWS RDS Proxy),并探讨了在 Kubernetes 中通过自定义服务、Operator 模式以及与 Istio 等服务网格集成的前沿实践。

最后,报告还涵盖了性能评估与监控的最佳实践,介绍了如何使用 Sysbench、Prometheus 等工具量化读写分离带来的性能增益并监控关键指标(如复制延迟)。报告以对未来技术趋势的展望作结,预测了云原生数据库、HTAP(混合事务/分析处理)以及智能化运维将如何进一步演进数据库架构。


第一部分:读写分离的核心概念与价值

在数字化浪潮席卷全球的今天,数据量呈爆炸式增长,应用系统的访问压力与日俱增。对于绝大多数依赖数据库的应用而言,数据库往往最先成为整个系统的性能瓶颈。在这样的背景下,读写分离作为一种经典且行之有效的数据库架构优化方案,被广泛应用于各类高并发场景中。

1.1 什么是读写分离?

读写分离(Read-Write Separation)是一种数据库架构设计模式,其核心思想是将数据库的负载根据操作类型进行拆分,由不同的数据库实例专门处理。具体而言:

  • 写操作(Write Operations)‍ :所有对数据产生变更的操作,如INSERTUPDATEDELETE,都被定向到一台或一组“主数据库”(Master/Primary)实例上。主库是数据的唯一写入点,是所有数据的权威来源。
  • 读操作(Read Operations)‍ :所有仅查询数据而不产生变更的操作,如SELECT,则被分发到一台或多台“从数据库”(Slave/Replica/Read-only)实例上。

为了保证从数据库能够提供有效的读取服务,必须有一种机制确保其数据与主数据库保持同步。这个过程被称为数据复制(Data Replication)‍。主数据库会将其执行的写操作(通常以二进制日志binlog或预写日志WAL的形式)持续地传输给从数据库。从数据库接收到这些日志后,会“重放”(Replay)这些操作,从而使自身的数据副本逐步追赶上主库的状态 。

这种“一主多从”(One Master, Multiple Slaves)的架构是读写分离最经典的拓扑结构 。通过这种方式,原本集中在单一数据库上的读写压力被有效分散,实现了负载的均衡。

1.2 为什么需要读写分离?

读写分离的需求并非凭空产生,而是由特定业务场景和技术瓶颈共同驱动的。

业务场景驱动:在互联网应用中,普遍存在一种“读多写少”的现象 。例如,一个电商网站,用户浏览商品(读操作)的频率远高于下单购买(写操作);一个内容平台,用户阅读文章(读操作)的频率远高于发布文章(写操作)。据统计,在许多应用中,读写请求的比例可能达到10:1甚至100:1。在这种场景下,大量的读请求会与写请求争夺同一数据库实例的CPU、内存、I/O和锁资源,导致整体性能下降。将读请求剥离出去,是应对这种不均衡负载的自然选择。

技术瓶颈驱动:当单一数据库实例的负载达到其物理极限(即“垂直扩展”的尽头)时,系统的响应时间会急剧增加,甚至出现大量请求超时。此时,通过增加更多的服务器来分担负载(即“水平扩展”)成为必然选择。读写分离正是数据库水平扩展最基础、最重要的一步。它允许我们通过简单地增加从数据库的数量,就能线性地提升系统的读取能力,而无需对复杂且关键的主数据库进行昂贵的垂直升级 。

1.3 读写分离的核心优势

实施读写分离架构能为系统带来多方面的显著收益:

  1. 性能提升与负载均衡 (Performance Improvement & Load Balancing)

    • 减轻主库压力:写操作通常比读操作更消耗资源,且常常伴随着锁竞争。将海量的读请求从主库剥离,可以使主库专注于处理核心的写事务,显著降低其负载,减少锁冲突和阻塞,从而提升写操作的响应速度和稳定性 。
    • 提升读取吞吐量:读请求可以被分发到多个从数据库上并行处理。通过增加从库的数量,整个系统的读并发能力和总吞吐量(QPS)可以得到近乎线性的扩展 。
  2. 高可用性与数据冗余 (High Availability & Data Redundancy)

    • 故障转移基础:从数据库本质上是主数据库的热备份。当主数据库因硬件故障、软件崩溃或维护而宕机时,系统可以将一个从数据库提升为新的主数据库,继续提供写服务,从而大大缩短系统的停机时间,保障业务的连续性 。
    • 读服务不中断:即使主库发生故障,只要从库仍在正常运行,系统的读服务就不会中断(或仅短暂中断),这对于用户体验至关重要。
    • 数据安全备份:多份数据副本的存在天然地提高了数据的安全性。除了用于线上服务的从库,还可以设置专门用于数据备份、离线分析或报表生成的从库,这些操作不会影响线上主库的性能 。
  3. 资源优化与可扩展性 (Resource Optimization & Scalability)

    • 弹性扩展能力:读写分离架构提供了出色的读取扩展性。当业务增长导致读压力增大时,只需横向增加更多的从库节点即可应对,这种扩展方式相比升级主库硬件成本更低、操作更灵活 。
    • 资源专门化:可以为主库和从库配置不同规格的硬件。例如,主库可以使用拥有高速I/O(如NVMe SSD)和强劲CPU的服务器以优化写性能,而从库则可以配置大内存的服务器以缓存更多热点数据,提高读性能,从而实现资源的最优配置 。

1.4 读写分离的挑战与权衡

尽管读写分离优势明显,但它并非“银弹”,引入这种架构也带来了一系列新的技术挑战和需要权衡的因素:

  1. 数据一致性问题 (Data Consistency)
    这是读写分离最核心的挑战。由于主从复制大多是异步或半同步的,从主库写入数据到该数据被同步到从库,中间存在一个时间窗口,这被称为复制延迟(Replication Lag)‍ 。如果延迟过大,应用可能会遇到以下问题:

    • 用户刚刚发布了一条内容(写入主库),刷新页面时却看不到(从从库读取),因为数据还没同步过来。
    • 在需要强一致性的场景下(如金融交易),读到旧数据可能会导致严重的业务逻辑错误。
      解决这个问题通常需要业务层面的妥协(如允许短暂不一致)、技术层面的优化(如优化网络、使用半同步复制)或架构层面的设计(如强制将某些关键读请求路由到主库)。
  2. 架构复杂性与维护成本 (Architectural Complexity & Maintenance Cost)

    • 引入新组件:读写分离架构需要引入额外的组件,如负载均衡器或数据库代理,并需要配置和维护主从复制链路 。
    • 管理复杂度:数据库实例从一个增加到多个,运维团队需要监控所有节点的状态、复制延迟、健康状况,并制定完善的故障转移预案。这无疑增加了管理的复杂度和工作量。
  3. 成本增加 (Cost Increase)

    • 硬件成本:增加从数据库服务器意味着需要更多的硬件或云资源投入 。
    • 人力成本:更复杂的架构需要更专业的DBA或运维工程师团队来维护,人力成本也随之上升。

因此,决定是否采用读写分离,需要综合评估业务特性(读写比例)、性能需求、可接受的一致性水平以及团队的技术实力和预算。


第二部分:读写分离的架构模式与实现层次

实现读写分离,本质上是要解决一个核心问题:如何将应用程序发出的 SQL 请求准确地路由到正确的数据库实例(主库或从库)‍。根据路由逻辑所在的位置,我们可以将实现方式划分为三个主要层次。

2.1 架构模式分类

  1. 应用层实现 (Application-Layer Implementation):路由逻辑直接嵌入在应用程序的代码中。应用程序自身负责判断每条SQL是读操作还是写操作,并据此选择连接主数据库或从数据库。
  2. 中间件代理实现 (Middleware Proxy Implementation):在应用程序和数据库之间引入一个独立的代理层(Proxy)。应用程序的所有数据库请求都发送给这个代理,由代理负责解析SQL、判断读写类型,并将请求转发给后端的相应数据库实例。
  3. 数据库驱动/原生方案 (Database Driver/Native Solution):利用数据库官方提供或社区开发的、与特定数据库紧密集成的组件(如增强版的JDBC/ODBC驱动或官方路由工具)来实现。这种方式通常与数据库自身的某些高级功能(如集群管理)相结合。

下面我们将对这三种层次的实现方式进行详细的解析。

2.2 实现层次详解

2.2.1 应用层代码实现

这是最直接也最原始的实现方式。开发人员在业务代码中显式地管理和切换数据源。

  • 原理:在应用程序中配置两个(或多个)数据源:一个指向主库(Write DataSource),另一个(或一组)指向从库(Read DataSource)。在执行数据库操作前,通过代码逻辑(如AOP切面、注解、或者简单的if-else判断)来决定本次操作应使用哪个数据源。

    • 例如,在Java的Spring框架中,可以继承AbstractRoutingDataSource类,重写determineCurrentLookupKey()方法。在该方法中,根据当前线程上下文中设置的标记(例如,一个标记是“read-only”还是“read-write”)来返回对应数据源的Key。业务代码在调用数据库操作前,先设置这个标记。
  • 优点

    • 高度灵活性:开发人员可以实现非常精细的控制逻辑。例如,可以基于用户的会话状态、特定业务逻辑(如“刚注册成功的用户,在接下来5秒内的所有读请求都走主库”以避免延迟问题)等复杂条件来决定路由策略。
    • 无额外组件:不需要部署和维护额外的代理服务器,架构相对简单。
  • 缺点

    • 高侵入性与耦合:数据库路由逻辑与业务代码紧密耦合,对应用程序有较强的侵入性。如果未来需要更换路由策略或数据库架构,可能需要大规模修改业务代码。
    • 开发与维护成本高:每个需要读写分离的应用都需要独立开发和维护这套逻辑,难以复用,增加了开发人员的心智负担和出错的可能性。
    • 连接池管理复杂:需要为每个数据源独立管理连接池,资源利用效率可能不高。
2.2.2 数据库中间件代理

这是目前业界最主流、最成熟的实现方式。它将读写分离的复杂性从应用层剥离,封装到一个独立的中间件服务中。

  • 原理:应用不再直接连接数据库,而是连接到一个数据库中间件代理。这个代理对外表现得就像一个单一的、功能强大的MySQL或PostgreSQL服务器。当代理收到应用的SQL请求后,它会:

    1. 解析SQL:分析SQL语句的类型(SELECT,INSERT,UPDATE,DELETE等)。
    2. 应用规则:根据预先配置的路由规则,决定该请求应发往写组(主库)还是读组(从库)。
    3. 转发请求:从目标组中选择一个健康的数据库实例(对于读组,还可以根据负载均衡算法选择),将请求转发过去。
    4. 返回结果:将数据库实例返回的结果再回传给应用程序。
  • 常见开源中间件

    • ProxySQL: 一个高性能、高可用的MySQL协议感知代理,以其强大的查询规则引擎和灵活性著称。
    • MyCat: 一个功能丰富的分布式数据库中间件,不仅支持读写分离,还支持分库分表。
    • ShardingSphere: Apache顶级项目,定位为分布式数据库生态系统,提供读写分离、分库分表、数据脱敏等多种功能,支持插件化扩展。
  • 优点

    • 对应用透明:应用程序无需关心后端的数据库是单个还是集群,只需像连接普通数据库一样连接中间件即可。数据库架构的变更对应用层完全透明,极大地降低了耦合度。
    • 功能强大且集中管理:中间件通常提供丰富的功能,如连接池、负载均衡、故障转移、SQL防火墙、监控统计等。所有路由逻辑和管理策略都集中在中间件层面配置,便于统一维护和升级。
    • 支持多语言/多应用:由于代理工作在数据库协议层,任何使用标准数据库驱动的应用程序(Java, Python, Go, PHP等)都可以无缝接入。
  • 缺点

    • 引入新的复杂度和单点风险:中间件本身成为系统中的一个关键组件,其稳定性和性能直接影响整个系统。需要对其进行高可用部署(如使用Keepalived或部署多个代理实例),这增加了架构的复杂性。
    • 性能开销:请求需要经过一次额外的网络跳转和解析,会带来一定的性能延迟(尽管现代高性能代理的开销通常很小,在毫秒级甚至微秒级)。
    • SQL兼容性问题:部分复杂或非标准的SQL语法可能不被中间件完全支持或正确解析。
2.2.3 数据库原生方案

这种方案利用数据库厂商自己提供的工具链来解决读写分离问题,通常与数据库的高可用集群方案深度集成。

  • 原理:通过一个官方提供的、了解数据库集群内部状态的智能路由组件来分发请求。这个组件能够实时感知集群的拓扑结构(谁是主、谁是从),并根据配置将读写请求路由到正确的节点。

  • 典型示例

    • MySQL InnoDB Cluster (MGR + MySQL Router):这是MySQL官方推出的高可用和读写分离解决方案。
      • MySQL Group Replication (MGR):负责维护一个多主(或单主)模式的数据库节点集群,保证数据强一致性和自动故障转移。
      • MySQL Router:是一个轻量级中间件,它能自动发现并连接到InnoDB Cluster,感知集群成员的角色变化。应用连接到MySQL Router暴露的不同端口,Router就会自动将流量进行读写分离 。
  • 优点

    • 官方支持与最佳集成:作为官方解决方案,其兼容性、稳定性以及与数据库新特性的集成度是最高的。
    • 简化配置与管理:通常提供自动化的部署和配置工具(如MySQL Shell),可以一键式创建集群和配置路由,大大降低了使用门槛 。
    • 智能感知拓扑:在发生主从切换时,路由组件能自动感知到新的主库,并无缝地切换写流量,对应用完全透明 。
  • 缺点

    • 厂商绑定:方案与特定数据库版本和技术栈深度绑定,缺乏通用性。
    • 灵活性可能受限:相比通用的中间件代理,其路由规则、负载均衡策略等可定制性可能没有那么强。

总结:这三种实现层次各有优劣,适用于不同的场景。应用层实现灵活但维护成本高,适合早期简单场景或有特殊定制化需求的系统。中间件代理方案功能强大且对应用透明,是目前大中型互联网公司的首选。数据库原生方案则为追求官方支持、简化运维和高集成度的企业提供了“一站式”解决方案。


第三部分:基于 MySQL 的读写分离实现方案

MySQL 作为全球最流行的开源关系型数据库,其读写分离生态系统非常成熟,提供了从原生复制到高级中间件的多种选择。本部分将详细介绍几种主流的 MySQL 读写分离实现方案。

3.1 方案一:原生复制 + ProxySQL

这是目前社区中最受欢迎和推崇的组合之一,它结合了 MySQL 原生复制的稳定性和 ProxySQL 代理的强大灵活性。

3.1.1 架构概述

该架构由三个核心组件构成:

  1. MySQL 主库 (Master):处理所有写操作。
  2. MySQL 从库 (Slaves):一个或多个,配置为read_only,处理读操作。主从之间通过 MySQL 原生的 Binlog 复制保持数据同步。
  3. ProxySQL 代理:作为流量入口,接收所有来自应用的数据库连接。它根据配置的规则将 SQL 请求智能地路由到后端的主库或从库。

工作流程

  1. 应用将数据库连接地址配置为 ProxySQL 的地址和端口。
  2. 应用发送一条 SQL(例如SELECT * FROM users WHERE id=1)。
  3. ProxySQL 接收到该 SQL,通过其内置的查询规则引擎进行匹配。
  4. 规则引擎发现^SELECT模式匹配成功,决定将此请求路由到“读组”。
  5. ProxySQL 从“读组”中的多个从库里,根据负载均衡算法(如轮询)选择一个健康的从库。
  6. ProxySQL 将请求转发给选定的从库,并将结果返回给应用。
  7. 如果应用发送UPDATE users SET name='new' WHERE id=1,ProxySQL 的规则(例如,不匹配^SELECT的默认走写组,或者有专门的^UPDATE规则)会将其路由到“写组”(即主库)。
3.1.2 详细配置步骤

下面是一个分步指南,演示如何从零开始搭建这套架构。

步骤一:配置 MySQL 主从复制 (Binlog Replication)

假设我们有两台服务器:主库192.168.1.10和从库192.168.1.11

1.配置主库 (/etc/my.cnf)

[mysqld] server-id = 10 # 必须唯一 log-bin = mysql-bin # 开启二进制日志 binlog-format = ROW # 强烈建议使用ROW格式,对读写分离最友好 [[341]][[358]] sync_binlog = 1 # 保证事务提交后binlog落盘,提高数据安全性 gtid_mode = ON # 建议开启GTID模式,简化故障转移 [[341]] enforce_gtid_consistency = ON

2.配置从库 (/etc/my.cnf)

[mysqld] server-id = 11 # 必须唯一 log-bin = mysql-bin # 从库也建议开启binlog,便于后续扩展 binlog-format = ROW read_only = 1 # 关键!将从库设为只读模式 [[341]][[353]] relay_log = relay-log # 中继日志配置 gtid_mode = ON enforce_gtid_consistency = ON

3.创建复制账号并授权

在主库上执行:

CREATE USER 'replicator'@'192.168.1.11' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'192.168.1.11'; FLUSH PRIVILEGES;

4.启动复制

在从库上执行(使用GTID模式):

CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_USER='replicator', MASTER_PASSWORD='password', MASTER_AUTO_POSITION=1; START SLAVE;

执行SHOW SLAVE STATUS\G确认Slave_IO_RunningSlave_SQL_Running均为Yes

步骤二:配置 ProxySQL

ProxySQL 的配置通过其管理接口(默认为 6032 端口)使用 SQL 语句完成。

1.连接 ProxySQL 管理接口

mysql -u admin -padmin -h 127.0.0.1 -P 6032

2.配置后端服务器 (mysql_servers)

我们将主库放入主机组10(写组),从库放入主机组20(读组)。

INSERT INTO mysql_servers (hostgroup_id, hostname, port) VALUES (10, '192.168.1.10', 3306), (20, '192.168.1.11', 3306);

加载配置到运行时并持久化到磁盘 :
sql LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;

3.配置用户 (mysql_users)

创建供应用程序连接的用户,并指定其默认的主机组。

INSERT INTO mysql_users (username, password, default_hostgroup) VALUES ('app_user', 'app_password', 10); -- 默认主机组通常设为写组

加载和保存:
sql LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK;

3.定义查询路由规则 (mysql_query_rules)

这是实现读写分离的核心。规则按rule_id从小到大依次匹配。

-- 规则1: 显式在事务中的读请求,路由到写组(主库),保证事务一致性 INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (10, 1, '^SELECT.*FOR UPDATE$', 10, 1), (11, 1, '^SELECT.*LOCK IN SHARE MODE$', 10, 1); -- 规则2: 所有以SELECT开头的读请求,路由到读组(从库) [[342]][[345]] INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES (20, 1, '^SELECT', 20, 1); -- 默认规则: 其他所有请求(INSERT, UPDATE, DELETE等)将由于没有匹配到上述规则,而被路由到用户的 `default_hostgroup`,即写组 10。

加载和保存规则 :
sql LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;

5.配置监控用户

ProxySQL 需要一个 MySQL 用户来监控后端节点的健康状况(如read_only状态和延迟)。
在主库和从库上创建监控用户:

CREATE USER 'monitor'@'%' IDENTIFIED BY 'monitor_password'; GRANT USAGE ON *.* TO 'monitor'@'%'; -- 只需要USAGE权限

在 ProxySQL 中配置:
sql UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username'; UPDATE global_variables SET variable_value='monitor_password' WHERE variable_name='mysql-monitor_password'; LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;

现在,应用程序只需将连接信息指向 ProxySQL 的客户端端口(默认为 6033),使用app_userapp_password即可实现透明的读写分离。

3.1.3 常见陷阱与最佳实践
  • read_only参数至关重要:ProxySQL 会定期检查后端节点的read_only状态。当与mysql_replication_hostgroups配合使用时,ProxySQL 会自动将read_only=0的节点识别为 writer,read_only=1的节点识别为 reader。因此,确保从库正确设置read_only=1是自动故障转移和路由的基础 。
  • 事务处理:一个事务中可能既有读又有写。如果读操作被路由到从库,而写操作路由到主库,可能会因为复制延迟而读到旧数据,导致逻辑错误。最佳实践是:
    • 通过 ProxySQL 规则将BEGIN/START TRANSACTION后的所有请求都路由到主库。
    • 在应用层面,将需要事务保证的操作封装在一个方法中,并通过特定注解或逻辑,强制该方法内所有数据库操作都走主库。
  • 主从延迟问题:对于某些对数据实时性要求高的读请求(如用户刚支付完,立即查询订单状态),可以采用特殊注释/*FORCE_MASTER*/ SELECT ...,并配置 ProxySQL 规则,将带有此注释的查询强制路由到主库。
  • 查询规则的精确性match_pattern使用正则表达式,编写不当可能导致路由错误。例如,^SELECT规则过于宽泛,可能会将SELECT ... FOR UPDATE也错误地路由到从库。因此,需要将更精确的规则(如FOR UPDATE)放在前面(rule_id更小)。

3.2 方案二:MySQL InnoDB Cluster (官方高可用方案)

这是 MySQL 官方提供的一套集高可用、读写分离、易用性于一体的完整解决方案。

3.2.1 架构概述

InnoDB Cluster 由三个紧密集成的组件构成 :

  1. MySQL Servers with Group Replication (MGR):MGR 是一个 MySQL 插件,它允许多个 MySQL 实例组成一个高可用的复制组。在单主模式下,组内只有一个节点可写(Primary),其他节点为只读(Secondaries),并自动进行故障转移。
  2. MySQL Shell:一个高级的命令行客户端和代码编辑器,是创建和管理 InnoDB Cluster 的主要工具。
  3. MySQL Router:一个轻量级智能代理,它连接到 InnoDB Cluster,自动获取集群元数据(拓扑结构、节点角色等),并为应用程序提供透明的读写分离和负载均衡 。
3.2.2 配置与使用

配置 InnoDB Cluster 异常简单:

1.安装组件:在所有节点上安装 MySQL Server, MySQL Shell, 和 MySQL Router。

2.创建集群:使用 MySQL Shell,通过几个简单的命令即可创建一个集群。

// 在第一个节点上 dba.createCluster('myCluster'); // 在其他节点上 cluster.addInstance('root@node2:3306'); cluster.addInstance('root@node3:3306');

3.引导 MySQL Router:在一台独立的服务器或应用服务器上,执行mysqlrouter命令进行自动配置。

mysqlrouter --bootstrap root@node1:3306 --user=mysqlrouter

此命令会连接到集群,获取元数据,并自动生成一个mysqlrouter.conf配置文件 。

  1. 连接应用:启动 MySQL Router 后,它会默认监听几个端口 :
    • Port 6446 (Read-Write):连接此端口的请求,写操作会被路由到 Primary 节点,读操作也会被路由到 Primary 节点(默认策略)。
    • Port 6447 (Read-Only):连接此端口的请求,会被负载均衡到所有 Secondary 节点。
    • 较新版本的 Router 还提供一个读写分离端口(如 6450),连接此端口后,Router 会自动将SELECT路由到从库,其他语句路由到主库,实现类似 ProxySQL 的透明分离 。
3.2.3 故障转移行为

InnoDB Cluster 的最大优势在于其无缝的故障转移能力。当 Primary 节点宕机时,MGR 会在组内自动选举一个新的 Primary。MySQL Router 会持续监控集群元数据,一旦检测到 Primary 变更,它会立即将后续的写请求路由到新的 Primary 节点,整个过程对应用程序完全透明,无需任何人工干预 。

3.2.4 与原生复制+ProxySQL方案的对比
特性InnoDB Cluster (MGR + Router)原生复制 + ProxySQL
数据一致性更高。MGR 基于 Paxos 协议,可实现“几乎同步”的复制,数据一致性强。相对较低。原生异步复制存在延迟,半同步复制可缓解但不能完全避免。
故障转移自动、官方。内置选举和切换机制。需手动或借助第三方工具(如 MHA, Orchestrator) 实现,ProxySQL 可配合这些工具。
配置复杂度。MySQL Shell 极大简化了部署和管理。。需要手动配置主从复制、ProxySQL 规则等,步骤繁琐。
灵活性相对较低。路由策略和功能由 Router 本身决定。极高。ProxySQL 的规则引擎非常强大,可实现极其复杂的路由和重写逻辑。
社区生态官方主导,生态相对封闭。社区驱动,生态开放,与各种监控、管理工具集成良好。
适用场景追求高可用、强一致、简化运维、信任官方解决方案的金融、政务等关键业务 。需要高度定制化路由、性能调优,技术实力较强,希望架构灵活可控的互联网公司。

3.3 方案三:基于 GTID 的复制

GTID (Global Transaction Identifier) 并非一个独立的读写分离方案,而是 MySQL 5.6 版本后引入的一种增强型复制技术,它可以与任何读写分离架构(如 ProxySQL、MGR)结合使用。

  • 原理与优势:传统复制基于binlog文件名和位置点(Position),在主从切换时,需要DBA手动寻找新主库的正确同步点,过程复杂且易出错。GTID 为数据库中的每一个事务分配一个全局唯一的ID。从库不再关心文件名和位置,只需告诉新主库“我已经执行到了哪些GTID”,新主库就会自动将后续的事务发送过来。这极大地简化了故障转移和集群拓扑变更的管理 。

  • 挑战与限制

    • 迁移成本:从传统模式迁移到 GTID 模式需要严格的步骤,通常需要短暂的停机窗口 。
    • SQL 限制:GTID 模式下,不支持在事务中混用事务性存储引擎(如InnoDB)和非事务性存储引擎(如MyISAM)的更新,且对CREATE TABLE ... SELECT等语句有限制 。

尽管有挑战,但考虑到其在简化运维和提升高可用性方面的巨大优势,在新项目中强烈建议默认开启 GTID 模式

3.4 方案四:Vitess (云原生分片中间件)

当数据量增长到单个主库也无法承载时,就需要进行水平分片(Sharding)‍ ,即将一个大表水平拆分到多个数据库实例中。Vitess 是一个诞生于 YouTube、现已成为 CNCF 毕业项目的开源数据库集群解决方案,它在读写分离的基础上,提供了强大的水平分片能力。

  • 架构与原理:Vitess 在应用和一组 MySQL 集群之间增加了一个智能代理层。

    • VTGate:无状态的代理,是应用的统一入口。它负责解析查询,从元数据中找到数据所在的分片,然后将请求路由到对应的VTTablet。它也负责实现读写分离 。
    • VTTablet:为每个 MySQL 实例部署一个VTTabletSidecar。它负责管理 MySQL 生命周期、重写查询、提供连接池等。
    • 分片与读写分离:一个逻辑上的表被分散到多个shard(分片),每个shard都是一个独立的 MySQL 主从复制集群。VTGate 会将写请求路由到分片的主库,读请求路由到分片的从库 。
  • 优势:Vitess 解决了原生 MySQL 在大规模集群管理上的诸多痛点,提供了在线分片(reshaarding)、模式迁移(schema migration)、高可用、连接池等企业级功能,被 Slack、GitHub 等众多大型公司用于生产环境 。

  • 适用场景:对于数据量巨大、预期会持续高速增长、需要水平扩展的超大规模应用,Vitess 是一个经过生产环境严苛考验的优秀选择。


第四部分:基于 PostgreSQL 的读写分离实现方案

PostgreSQL,以其强大的功能、高标准的SQL兼容性和卓越的扩展性,在近年来获得了越来越多的关注。其读写分离方案同样成熟可靠。

4.1 方案:原生复制 + pgpool-II

与 MySQL 的“原生复制+ProxySQL”组合类似,PostgreSQL 社区最常用的读写分离方案是利用其强大的原生复制能力,并配合中间件pgpool-II

4.1.1 pgpool-II 架构与功能

pgpool-II是一个功能全面的 PostgreSQL 中间件,它集多种功能于一身 :

  • 连接池 (Connection Pooling):复用数据库连接,减少频繁创建和销毁连接的开销。
  • 读写分离/负载均衡 (Read-Write Splitting / Load Balancing):自动将读请求分发到多个备库,写请求发往主库。
  • 高可用/自动故障转移 (High Availability / Automated Failover):监控后端节点健康,当主库故障时可自动执行故障转移脚本,并提升一个备库为新主库。
  • 在线恢复 (Online Recovery):提供命令来恢复故障的节点并重新加入集群。
4.1.2 详细配置步骤

下面是使用 pgpool-II 和 PostgreSQL 流复制(Streaming Replication)实现读写分离的配置概览。

步骤一:配置 PostgreSQL 主从复制 (流复制)

PostgreSQL 的流复制基于 WAL (Write-Ahead Logging) 日志。

1.主库配置 (postgresql.conf):

listen_addresses = '*' wal_level = replica # 开启复制所需的WAL级别 max_wal_senders = 10 # 最大并发复制连接数 archive_mode = on # 开启归档,用于PITR恢复 archive_command = 'cp %p /path/to/archive/%f'

2.主库配置 (pg_hba.conf):

允许备库连接以进行复制。

# TYPE DATABASE USER ADDRESS METHOD host replication replicator 192.168.1.21/32 md5

3.创建复制用户:

在主库上执行:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'password';

4.配置备库:

  • 使用pg_basebackup工具从主库克隆数据。
  • 创建recovery.conf文件(或在postgresql.conf中配置,取决于版本):
standby_mode = on primary_conninfo = 'host=192.168.1.20 port=5432 user=replicator password=password' trigger_file = '/tmp/postgresql.trigger.5432'
步骤二:配置 pgpool-II
  1. 安装 pgpool-II

  2. 配置pgpool.conf:
    这是 pgpool-II 的核心配置文件 。

# 连接设置 listen_addresses = '*' port = 9999 # 后端节点定义 backend_hostname0 = '192.168.1.20' backend_port0 = 5432 backend_weight0 = 1 backend_data_directory0 = '/var/lib/pgsql/13/data' backend_flag0 = 'ALWAYS_PRIMARY' # 可以指定主库 backend_hostname1 = '192.168.1.21' backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/var/lib/pgsql/13/data' backend_flag1 = 'DISALLOW_TO_FAILOVER' # 启用读写分离和负载均衡 master_slave_mode = on master_slave_sub_mode = 'stream' # 使用流复制模式 [[111]][[113]] load_balance_mode = on # 启用读请求的负载均衡 [[370]] # 健康检查和故障转移 health_check_period = 10 failover_command = '/path/to/failover.sh %d %H %p %D %m %M %P %r %R'

3.配置认证 (pool_hba.conf):

配置哪些客户端可以连接 pgpool-II。

# TYPE DATABASE USER ADDRESS METHOD host all all 192.168.1.0/24 md5

4.启动 pgpool-II并将应用连接到 pgpool-II 的9999端口。pgpool-II 会自动将SELECT查询分发到备库,而INSERT/UPDATE/DELETE发往主库 。

4.1.3 逻辑复制与复制槽

PostgreSQL 10 之后引入的逻辑复制是一种更灵活的复制方式。它不是物理地复制整个数据块,而是复制逻辑上的数据变更(如行的增删改)。这使得它可以实现跨版本复制、选择性复制(只复制某些表)等高级功能 。

  • 复制槽 (Replication Slot):为了防止在备库离线时主库过早清理掉备库尚未接收的 WAL 日志,PostgreSQL 引入了复制槽。主库会为每个备库创建一个复制槽,并保证在备库确认接收之前,不会删除相关的 WAL 日志。创建复制槽的命令是pg_create_logical_replication_slot。pgpool-II 可以与逻辑复制结合,但配置上更为复杂。
4.1.4 与 MySQL 方案的比较
特性PostgreSQL + pgpool-IIMySQL + ProxySQL
中间件定位pgpool-II 是一个“全能选手”,集成了连接池、负载均衡、高可用等多种功能。ProxySQL 更专注于协议代理和查询路由,功能纯粹且高性能。高可用通常依赖外部工具。
复制技术流复制非常成熟稳定,被认为比 MySQL 的传统复制更可靠 。逻辑复制提供了更高的灵活性。Binlog 复制广泛使用,GTID 模式极大地改善了可用性。
配置与生态pgpool-II 配置项繁多,学习曲线较陡。生态相对 MySQL 较小。ProxySQL 配置相对直观,MySQL 生态庞大,社区活跃,解决方案丰富。
性能pgpool-II 在进行 SQL 解析和路由时可能引入一些性能开销,尤其是在高并发下 。ProxySQL 以高性能著称,其多线程模型和高效的规则引擎使其延迟极低。

总的来说,两者都能很好地实现读写分离。PostgreSQL 的方案更倾向于一个大而全的中间件,而 MySQL 的方案则更倾向于组件化、各司其职的组合。


第五部分:云环境下的读写分离

云计算时代,各大云厂商将读写分离这类复杂的数据库架构能力,封装成了简单易用的托管服务,极大地降低了用户的运维成本。

5.1 主流云厂商的托管式服务

几乎所有主流的云数据库服务(DBaaS)都内置了读写分离功能。

5.1.1 AWS (Amazon Web Services)
  • Amazon RDS:用户可以为主数据库实例(MySQL, PostgreSQL, MariaDB 等)一键创建多个只读副本(Read Replicas)‍。应用通过连接到不同的数据库端点(Endpoint)来区分读写。主实例一个端点,每个只读副本一个端点。
  • Amazon Aurora:作为 AWS 的云原生关系型数据库,其架构本身就是为读写分离和高可用设计的。所有实例共享同一份存储卷,写操作发往 Writer 实例,读操作可由多个 Reader 实例处理。Aurora 提供了集群端点(Cluster Endpoint)‍ 和只读端点(Reader Endpoint)‍ ,应用连接只读端点,Aurora 会自动在所有 Reader 实例间进行负载均衡。
  • AWS RDS Proxy:这是一个完全托管的数据库代理服务。它可以为 RDS 和 Aurora 提供连接池、增强的安全性和透明的故障转移。更重要的是,RDS Proxy 可以自动实现读写分离。应用只需连接到代理的端点,代理会将写请求路由到主实例,读请求路由到只读副本,对应用完全透明 。
5.1.2 阿里云
  • ApsaraDB RDS:与 AWS RDS 类似,用户可以创建只读实例。阿里云进一步提供了数据库代理(Database Proxy)‍ 服务。开启该服务后,RDS 会提供一个统一的读写分离地址。应用连接此地址,代理会自动将请求路由到主实例或只读实例,无需应用层做任何修改 。
  • PolarDB:阿里云的云原生数据库,架构类似 Aurora,采用存储计算分离、一写多读的设计。同样提供集群地址和读写分离地址,简化了应用开发。
5.1.3 Google Cloud Platform (GCP)
  • Cloud SQL:GCP 的托管数据库服务,同样支持为 MySQL, PostgreSQL, SQL Server 创建只读副本,并为每个副本提供独立的 IP 地址。
  • Cloud SQL Proxy:该代理的主要作用是提供一个安全的、通过 IAM 认证的数据库连接方式,特别适用于从 GKE (Google Kubernetes Engine) 或本地环境连接 Cloud SQL。它本身并不直接提供读写分离路由功能,读写分离仍需应用连接不同的实例 IP 来实现 。
5.1.4 托管服务的优势与注意事项
  • 优势

    • 极简运维:一键创建只读副本,自动配置复制,无需关心底层细节 。
    • 高可用与弹性:内置自动故障转移和负载均衡,可根据负载自动或手动扩展只读实例数量。
    • 与云生态集成:与云上的监控、告警、备份等服务无缝集成。
  • 注意事项

    • 成本与厂商锁定:托管服务通常比自建更昂贵,并且会加深对特定云厂商的依赖 。
    • 复制延迟:跨可用区或跨地域的只读副本会存在显著的复制延迟,业务设计必须考虑这一点 。
    • 配置灵活性:虽然使用简单,但可定制化程度不如自建 ProxySQL 等方案。

5.2 Kubernetes 环境下的读写分离

在 Kubernetes 这个云原生操作系统上部署有状态的数据库并实现读写分离,是业界一个热门且具有挑战性的课题。

5.2.1 实现模式
  1. 模式一:自定义服务 (Custom Services)
    这是最基础的实现方式。假设我们在 K8s 中通过StatefulSet部署了一个一主多从的 MySQL 集群。

    • 部署:使用StatefulSet部署 MySQL,确保每个 Pod 都有稳定的网络标识和持久化存储(PVC)。
    • 服务发现:创建两个Service
      • mysql-write-svc:这个Serviceselector只选择标签为role=master的主库 Pod。
      • mysql-read-svc:这个Serviceselector选择标签为role=slave的所有从库 Pod。
    • 应用连接:应用程序在配置中注入这两个Service的 DNS 名称 (mysql-write-svc.namespace.svc.cluster.localmysql-read-svc.namespace.svc.cluster.local),并在代码中根据操作类型选择连接哪个服务 。
    • 缺点:这种方式将读写分离的逻辑又带回了应用层,存在应用层实现的所有缺点。
  2. 模式二:使用数据库 Operator
    Operator 模式是 K8s 管理有状态应用的最佳实践。

    • 原理:数据库 Operator 是一个自定义的 K8s 控制器,它封装了部署、管理、扩缩容、备份、故障转移等所有数据库运维的专业知识。
    • 示例
      • Presslabs MySQL OperatorPercona Operator for MySQL:用户只需创建一个MysqlCluster类型的自定义资源(CRD),在 YAML 中定义replicas: 3,Operator 就会自动创建StatefulSet、配置主从复制、设置Service,甚至可以自动创建用于读写分离的Service
      • Vitess Operator: 在 K8s 中部署和管理 Vitess 集群变得极其简单。Operator 会自动处理 VTGate, VTTablet 等所有组件的部署和生命周期管理 。
    • 优势:极大地自动化和简化了在 K8s 中运行复杂数据库集群的工作。
  3. 模式三:集成服务网格 (Service Mesh)
    当应用部署在像 Istio 这样的服务网格中时,可以利用服务网格的能力来辅助实现更优雅的外部数据库访问。

    • 背景:云数据库通常位于 K8s 集群外部。应用 Pod 访问云数据库的流量属于“出站流量”(Egress Traffic)。
    • 集成思路:在应用 Pod 中,除了业务容器外,再部署一个数据库代理 Sidecar。这个 Sidecar 可以是云厂商提供的官方代理(如cloud-sql-proxy)也可以是通用的代理。
      • 业务应用连接localhost上的代理端口。
      • 代理负责安全地连接到外部的云数据库。
      • Istio 的 Sidecar(如 Envoy)拦截应用到数据库代理的流量。
    • Istio 发挥的作用
      • 流量路由:虽然 Istio 本身不解析数据库协议,无法做到像 ProxySQL 那样的读写分离,但它可以管理到不同外部服务的流量。例如,可以创建两个ServiceEntry对象来代表外部的主库地址和只读副本地址,然后通过VirtualService规则,将应用发往不同“伪主机名”的流量导向不同的外部ServiceEntry
      • 安全性增强:Istio 可以为应用到数据库代理之间的通信强制启用 mTLS 加密,即使它们都在同一个 Pod 内。对于出站到云数据库的流量,可以通过Egress Gateway进行统一管理和审计 。
      • 可观测性:Istio 可以提供应用访问数据库代理的详细遥测数据(Metrics, Logs, Traces),而无需应用或代理本身做任何修改。

最佳实践(推断)‍ :将云厂商提供的官方代理(如 AWS RDS Proxy, GCP Cloud SQL Proxy)作为 Sidecar 与应用部署在一起,是连接云数据库的安全、高效方式。应用代码只需连接localhost。然后,利用 Istio 的ServiceEntryDestinationRule来定义和保护到这些外部数据库代理服务的连接策略(如 TLS、超时、重试),从而将数据库访问也纳入服务网格的统一治理体系中。


第六部分:性能评估与监控

实施读写分离后,如何量化其带来的性能提升,并持续监控其运行状况,是确保架构稳定性的关键。

6.1 关键性能指标

  • 吞吐量 (Throughput):即 QPS(Queries Per Second)或 TPS(Transactions Per Second)。这是衡量数据库处理能力最核心的指标。实施读写分离后,读 QPS 和总 QPS 应该有显著提升 。
  • 响应时间/延迟 (Latency):每个请求从发出到收到响应所需的时间。应分别关注读请求和写请求的平均延迟、95%分位延迟、99%分位延迟。
  • 复制延迟 (Replication Lag):从库数据相对于主库数据的延迟时间。在 MySQL 中,通常通过SHOW SLAVE STATUS\G中的Seconds_Behind_Master来衡量。这是读写分离架构最重要的健康指标,必须严密监控。延迟过高会导致数据不一致问题,甚至引发连锁反应 。
  • 资源使用率:主库和从库的 CPU、内存、I/O、网络使用率。

6.2 性能测试工具

Sysbench是业界公认的、用于数据库性能基准测试的开源工具。它可以模拟复杂的多线程 OLTP(在线事务处理)负载 。

如何使用 Sysbench 测试读写分离架构

1.准备测试数据:使用 Sysbench 的oltp_common脚本准备数据。

sysbench oltp_common --db-driver=mysql --mysql-db=test --mysql-user=root --mysql-password=pw --table-size=1000000 prepare

2.编写测试脚本:Sysbench 允许使用 Lua 脚本自定义测试场景。可以编写一个包含读写操作的脚本,例如oltp_read_write.lua

3.运行测试

基线测试(无读写分离)‍ :将所有请求发往单一主库。

sysbench oltp_read_write --db-driver=mysql --mysql-host=master_ip --table-size=1000000 --threads=64 --time=300 run

读写分离测试:将请求发往读写分离代理(如 ProxySQL)。

sysbench oltp_read_write --db-driver=mysql --mysql-host=proxysql_ip --mysql-port=6033 --table-size=1000000 --threads=64 --time=300 run
  1. 分析结果:比较两次测试的 TPS、QPS、延迟等指标,量化读写分离带来的性能增益。

6.3 监控工具与实践

  • Prometheus + Grafana:这是当前最流行的开源监控组合。

    • mysqld_exporter: 部署在每个 MySQL 实例旁,采集 MySQL 的内部状态(包括Seconds_Behind_Master)并暴露给 Prometheus。
    • proxysql_exporter: 采集 ProxySQL 的内部指标,如连接数、路由命中率、查询延迟等。
    • Grafana: 使用预置的 Dashboard 或自定义 Dashboard,将 Prometheus 采集的数据可视化,创建告警规则(例如,当Seconds_Behind_Master> 10秒时告警)。
  • Percona Monitoring and Management (PMM):Percona 公司提供的开源数据库监控平台,专门针对 MySQL、PostgreSQL、MongoDB 进行了深度优化,提供了非常丰富的监控视图和查询分析(QAN)功能。

  • pt-query-digest:Percona Toolkit 中的一个工具,用于分析 MySQL 的慢查询日志,可以找出执行频率最高、最耗时的查询,是进行 SQL 优化的利器。

核心监控项

  • 主库:写 QPS、事务执行率、CPU/IO 负载。
  • 从库:读 QPS、CPU/内存负载、Seconds_Behind_Master(必须设置严格的告警阈值)。
  • 代理:活动连接数、客户端连接数、后端连接池状态、规则匹配统计、查询延迟。

第七部分:结论与未来展望

7.1 核心要点总结

读写分离是应对高并发、读密集型应用性能挑战的基石性架构。它通过牺牲一定的数据一致性(复制延迟),换取了系统整体性能、可用性和扩展性的巨大提升。其实现方式多样,从简单的应用层改造,到强大的中间件代理,再到云厂商提供的一站式托管服务,企业可以根据自身情况灵活选择。无论选择哪种方案,理解其背后的原理、权衡其利弊、并建立完善的监控体系,都是成功实施读写分离的关键。

7.2 技术选型建议

  • 初创公司/小型业务:如果读写压力不大,或预算有限,可以先不采用读写分离。当性能瓶颈出现时,可以优先考虑使用云厂商提供的托管式读写分离服务(如阿里云RDS的数据库代理),这是成本效益最高、上手最快的方式。
  • 中大型互联网公司:这类公司业务复杂、流量巨大、对系统自主可控性要求高。‍“MySQL/PostgreSQL 原生复制 + 开源中间件(ProxySQL/pgpool-II)”‍ 是最主流和推荐的选择。它提供了强大的功能和灵活性,能够满足各种复杂的业务需求和性能调优。
  • 金融、电信等关键行业:对数据一致性和可用性要求极为苛刻。推荐使用官方高可用集群方案(如 MySQL InnoDB Cluster)或经过严格验证的商业解决方案
  • 需要水平扩展的巨型应用:当单主库的写性能成为瓶颈时,应考虑引入分库分表方案,如VitessShardingSphere
  • 全面拥抱 K8s 的团队:应优先考虑使用Operator模式来部署和管理数据库,并探索与服务网格集成的方案,以实现云原生环境下的统一治理。

7.3 未来发展趋势

展望未来,数据库架构仍在不断演进,读写分离这一经典模式也将被新的技术浪潮所影响和重塑。

  1. 云原生数据库的普及:以 Amazon Aurora、阿里云 PolarDB、Google AlloyDB 为代表的云原生数据库,通过存储计算分离、日志即数据库等创新架构,从根本上重构了复制和读写扩展的模式。它们能够提供秒级创建只读副本、跨可用区共享存储、Serverless 弹性伸缩等能力,将读写分离的易用性和性能推向了新的高度 。
  2. HTAP (Hybrid Transactional/Analytical Processing) 的兴起:以 TiDB、CockroachDB 为代表的分布式 NewSQL 数据库,试图在同一套系统中同时支持高并发的 OLTP(在线事务处理)和复杂的 OLAP(在线分析处理)负载。它们通过特殊的存储引擎(如列存副本)和智能查询优化器,可以在内部自动将分析型查询路由到专门的副本上,实现了“智能的内置读写分离”,减少了传统架构的复杂性。
  3. 中间件与服务网格的融合:未来,数据库中间件可能会以 Sidecar 的形式更紧密地与应用部署在一起,并与 Istio 等服务网格控制平面进行深度集成。服务网格负责服务发现、流量治理和安全策略下发,而数据库 Sidecar 则专注于协议解析、SQL 路由、高级缓存等专业领域,二者协同工作,形成更强大、更智能的数据访问层。
  4. 智能化运维 (AIOps):借助机器学习,未来的数据库管理平台将能够自动预测负载变化、智能调整从库数量、主动发现并修复复制延迟问题、甚至自动进行 SQL 优化和索引推荐,将数据库运维从“人治”推向“智治”。

总而言之,读写分离作为一种架构思想将长期存在,但其具体的实现形态正变得越来越透明、智能和自动化。对于技术人员而言,理解其核心原理,并紧跟云原生和智能化的发展趋势,将是构建未来高性能、高可用应用系统的关键所在。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/22 4:11:47

购物车小球动画:点击商品生成飞向购物车的小球动画

最近做了一个小需求,写购物车小球动画效果,给大家分享一下这个功能的源码,以便以后的使用。实现逻辑 每次点击时,拿到点击的位置作为小球的开始位置,再获取到购物车的结束位置。确定了两端位置之后,给小球设置css的pat…

作者头像 李华
网站建设 2025/12/27 12:31:57

16、文档编写工具与 XML 的使用指南

文档编写工具与 XML 的使用指南 1. 基础文档编写工具 1.1 纯文本文件的使用 在文档编写中,最小的实体是纯文本文件。只要文件包含的信息不过多,采用简单的结构就足够了。这里不需要使用 XML,通过标题、段落、缩进以及条目间留出足够的空间,就可以对信息进行结构化处理。…

作者头像 李华
网站建设 2025/12/22 7:02:23

21、Unix/Linux 系统安全与网络监控指南

Unix/Linux 系统安全与网络监控指南 1. 文件传输安全 在 Unix/Linux 系统中,文件传输是常见操作。当地址中省略用户名部分时,系统会使用当前用户名。若要保留文件的权限和所有权,可使用 -p 选项;若要复制目录树,则使用 -r (递归)选项。例如: erikk@unixhost>…

作者头像 李华
网站建设 2026/1/3 3:25:45

如何使用VSCode开发Arduino项目

安装必要插件在VSCode中安装官方扩展"PlatformIO IDE"或"Arduino"。PlatformIO功能更全面,支持多平台开发;Arduino扩展更轻量,适合简单项目。配置开发环境PlatformIO方式: 安装完成后,左侧工具栏会…

作者头像 李华
网站建设 2025/12/29 11:25:02

端到端测试优化:Cypress并行执行提速300%

在持续交付成为主流的今天,端到端测试作为确保软件质量的关键环节,其执行效率直接关系到产品迭代速度。传统的线性测试模式在面对复杂业务场景时往往成为瓶颈,而Cypress作为现代Web测试框架,通过并行化改造实现300%的效率跃升&…

作者头像 李华