antirez 自动编程与 Vibe Coding 概念辨析一、新闻概述1. 标题Redis 创始人 antirez 提出"自动编程"概念：编程可自动化，愿景不可2. 发布时间2026 年 2 月 1 日3. 来源antirez 个人博客二、核心内容1. 事件摘要A. 主要内容Redis 创始人 Salvatore Sanfilippo（网名 antirez）在其博客发表文章，正式提出"自动编程"（Automatic Programming）这一术语，用于描述专业程序员使用 AI 辅助开发的工作方式，并将其与"Vibe Coding"（氛围编程）进行明确区分。B. 核心亮点提出 Automatic Programming 与 Vibe Coding 的本质区别强调代码所有权归属开发者以 Redis 为例阐述"愿景"的重要性核心论断：编程已可自动化，愿景尚不能2. 关键信息A. 术语定义Automatic Programming（自动编程）：程序员深度参与的 AI 辅助开发Vibe Coding（氛围编程）：用户笼统描述需求，几乎不参与生成过程B. 重要观点预训练数据是人类集体的"礼物"（collective gift）通过自动编程产生的代码属于开发者本人Redis 的成功源于其中蕴含的理念和愿景，而非技术新颖性C. 涉及领域AI 辅助编程、软件开发方法论、开发者工具3. 背景介绍A. 作者背景antirez（Salvatore Sanfilippo）是意大利程序员，Redis 数据库的创始人。他于 2009 年创建 Redis，该项目后被 GitHub、Instagram、Twitter 等公司广泛采用。2020 年，他宣布辞去 Redis 项目维护者角色，专注于个人创作。B. 相关上下文"Vibe Coding"一词由前 Tesla AI 总监、OpenAI 研究员 Andrej Karpathy 于 2024 年 2 月提出，描述一种"完全沉浸于氛围，拥抱指数级增长，忘记代码存在"的编程方式。该术语迅速流行，但也引发了关于 AI 编程方式的讨论。三、详细报道1. 两种 AI 编程方式的区分A. Vibe Coding（氛围编程）antirez 对 Vibe Coding 的定义：用户以非常笼统的方式描述需求对代码生成过程几乎不参与最多只是报告问题或不符合预期的地方适合让软件开发"民主化"，让非程序员也能创建软件antirez 认为 Vibe Coding 是可以接受的方式，它降低了软件开发的门槛。B. Automatic Programming（自动编程）antirez 提出的自动编程定义：程序员深度参与整个开发过程通过直觉、设计和持续引导来控制产出严格遵循开发者对软件的愿景愿景可以是高层次的架构，也可以细化到具体函数的实现2. 核心差异分析graph TB subgraph "Vibe Coding" A1[用户] -->|笼统描述| B1[AI] B1 -->|生成代码| C1[软件] A1 -.->|报告问题| B1 end subgraph "Automatic Programming" A2[程序员] -->|愿景+设计| B2[AI] A2 -->|持续引导| B2 A2 -->|代码审查| B2 B2 -->|生成代码| C2[软件] A2 -->|深度参与| C2 end维度Vibe CodingAutomatic Programming参与程度低，仅描述需求高，全程深度参与控制力度弱，被动接受结果强，主动引导方向适用人群非程序员、快速原型专业程序员代码理解可能不理解生成的代码完全理解并掌控代码愿景体现AI 主导开发者主导3. 代码所有权论述antirez 在文章中强调了一个重要观点：通过自动编程产生的代码属于开发者本人。他的论证逻辑：AI 模型的预训练数据来自人类集体贡献这些数据是一种"集体礼物"（collective gift）开发者使用 AI 工具时，是在利用这份集体智慧但最终产出的软件体现的是开发者的愿景和设计用 antirez 的原话说："it is the software you are producing"（这是你正在创造的软件）。4. Redis 案例分析antirez 以自己创建的 Redis 为例，阐述愿景的重要性：A. 技术层面Redis 在技术上并无太多新颖之处：基础数据结构（哈希表、链表、跳表等）标准网络代码内存数据库的常见实现B. 成功因素Redis 之所以成功，是因为其中蕴含的理念和愿景：简洁的 API 设计对性能的极致追求对开发者体验的重视清晰的使用场景定位这个例子说明：技术实现可以被复制或自动化，但产品愿景是独特的、不可替代的。5. 核心论断antirez 文章的核心论断："Programming is now automatic, vision is not (yet)."编程已经可以自动化，但愿景（尚）不能。这一论断包含两层含义：AI 已经能够胜任大部分编程实现工作但软件的愿景、设计理念、产品方向仍需人类主导四、影响分析1. 行业影响A. 开发者角色转变从"代码编写者"转向"愿景设计者"技术实现能力的重要性相对下降产品思维和设计能力的重要性上升B. 技术趋势AI 编程工具将继续普及专业程序员与 AI 的协作模式将成为主流"自动编程"可能成为行业标准术语2. 用户影响A. 专业程序员需要学习如何有效引导 AI需要更强的架构设计和产品思维能力编码效率可能大幅提升B. 非程序员Vibe Coding 降低了软件开发门槛可以创建简单应用满足个人需求但复杂软件仍需专业程序员参与C. 企业需要重新评估开发团队的能力结构可能需要更多具有产品思维的技术人员开发效率有望提升，但质量把控仍需人工3. 技术趋势A. 短期趋势AI 编程工具的功能将持续增强更多开发者将采用 AI 辅助开发关于代码所有权的讨论将持续B. 长期展望AI 可能逐步具备一定的"愿景"能力人机协作模式将不断演进软件开发的本质可能发生根本性变化五、各方反应1. 作者观点antirez 在其 YouTube 频道中开始使用"自动编程"这一术语，他认为这很快将成为软件开发的标准方式。他对 Vibe Coding 持开放态度，认为它有助于软件开发的民主化。2. 业内评价A. 术语区分的意义antirez 的区分有助于澄清 AI 编程的不同使用场景：Vibe Coding 适合快速原型和非专业场景Automatic Programming 适合专业软件开发B. 愿景论的启示强调愿景的重要性，提醒开发者不要过度依赖 AI，而忽视了软件设计的核心价值。3. 社区反馈A. 正面评价术语区分清晰，有助于行业讨论代码所有权论述有说服力Redis 案例生动说明了愿景的价值B. 讨论焦点AI 是否终将具备"愿景"能力自动编程与传统编程的边界在哪里如何培养下一代程序员的愿景能力六、作者背景1. 个人简介Salvatore Sanfilippo（antirez）是意大利程序员，出生于西西里岛。他在信息安全领域起步，发明了著名的 Idle Scan 攻击技术，创建了 hping 网络工具。2. Redis 创建历程2009 年：为解决 LLOOGG 项目的性能问题，创建了 Redis 的前身 LMDB2009 年 2 月：在 Hacker News 发布 Redis，获得 Ruby 社区关注2010 年：GitHub、Instagram、Twitter 等公司开始采用 Redis2020 年：宣布辞去 Redis 项目维护者角色3. 近期动态离开 Redis 项目后，antirez 于 2022 年出版了科幻小说《Wohpe》，并在 YouTube 频道分享编程和技术见解。七、相关链接1. 原文链接antirez 博客原文2. 相关概念Vibe Coding 维基百科Andrej Karpathy 关于 Vibe Coding 的原始定义3. 作者资料antirez GitHub 主页Redis 官方网站参考资料Automatic Programming - antirezStory: Redis and its creator antirezVibe Coding - WikipediaWhat is Vibe Coding - Google Cloud
MySQL 在 2026 年不再是真正的开源软件技术分析
MySQL 在 2026 年不再是真正的开源软件技术分析一、新闻概述1. 标题停止在 2026 年使用 MySQL，它不是真正的开源软件2. 发布时间2026 年 1 月 11 日3. 来源Optimized by Otto二、核心内容1. 事件摘要A. 主要内容Otto Kekalainen 发布文章呼吁在 2026 年停止使用 MySQL，转而使用 MariaDB。文章指出 MySQL 虽然使用 GPL 开源协议，但并非真正的开源项目，开发过程完全闭门进行，社区贡献受到限制。B. 核心亮点MySQL GitHub 提交量在 2025 年显著下降Oracle 收购后 MySQL 社区逐渐萎缩MySQL 技术质量从 2022 年开始明显下滑2025 年 MySQL 公布 123 个 CVE，而 MariaDB 仅 8 个2. 关键信息A. 涉及产品MySQL 8.0/8.4/9.5MariaDBPercona ServerTiDBB. 重要数据2025 年 MySQL CVE 数量：123 个2025 年 MariaDB CVE 数量：8 个全球 57% 的 WordPress 网站使用 MariaDBMySQL 9.5 写密集型工作负载吞吐量比 8.0 下降约 15%C. 历史背景2009 年 Oracle 收购 Sun Microsystems 和 MySQL2018 年 MySQL 8.0 发布2024 年 MySQL 8.4 LTS 发布2025 年 Oracle 大幅削减 MySQL 团队人员三、详细报道1. 开源性质问题A. 开发模式对比graph LR subgraph MySQL_开发模式 M1[Oracle 内部开发] --> M2[闭门开发] M2 --> M3[社区提交 PR] M3 --> M4[无反馈/被忽略] M4 --> M5[发布新版本] end subgraph MariaDB_开发模式 N1[GitHub 公开开发] --> N2[实时审查] N2 --> N3[社区参与讨论] N3 --> N4[Jira 公开追踪] N4 --> N5[透明发布] endB. MySQL 社区问题所有开发在闭门环境中进行公开 Bug 跟踪器并非 Oracle 实际使用的系统社区提交的 Pull Request 缺乏反馈代码变更通常被重写，原作者仅在博客中获小额提及Git 作者/提交者字段仅包含 Oracle 员工C. MariaDB 开放模式所有开发在 github.com/mariadb/server 实时进行任何人都可以提交 Pull Request 并获得审查所有 Bug 在 jira.mariadb.org 公开讨论符合真正开源项目的运作模式2. 技术质量下滑A. 关键技术问题版本问题影响MySQL 8.0.29ALTER TABLE 默认 in-place 有边界情况缺陷数据库崩溃、数据损坏MySQL 8.0.32一年后才完全修复用户数据风险持续MySQL 8.1仅作为短期预览版本功能不完整MySQL 8.4 LTS新功能极少用户失望MySQL 9.5写密集型工作负载性能下降 15%性能退化B. 版本发布问题8.0 系列被宣布为"常青"版本小版本引入功能变更而非仅修复 Bug6 年无新的主要版本（2018-2024）升级路径困难（5.7->8.0、8.0->8.4）大量功能废弃导致迁移复杂C. 性能退化对比graph LR A[MySQL 8.0] -->|基线性能| B[100%] B -->|MySQL 9.5| C[85%] C -->|下降| D[15%] D --> E[工作负载: 写密集型]3. 安全与透明度A. CVE 数量对比（2025）数据库CVE 数量独有 CVEMySQL123117MariaDB8-B. 安全处理方式差异MySQL：CVE 描述缺乏详细信息示例：CVE-2025-53067 仅说明"高权限攻击者可通过多种协议轻易利用"无可验证的漏洞细节用户必须信任 Oracle 声称已修复典型描述："Easily exploitable vulnerability allows high privileged attacker with network access via multiple protocols to compromise MySQL Server"真正的开源项目：安全问题在禁运期结束后完全公开代码修复可供全面审查可验证漏洞存在性和修复有效性社区可审查修复方案是否充分C. 安全影响分析graph TD A[闭源安全处理] --> B[缺乏详细信息] B --> C[无法验证漏洞] C --> D[无法审查修复] D --> E[完全依赖供应商信任] E --> F[增加安全风险] G[开源安全处理] --> H[完整漏洞信息] H --> I[代码公开可审] I --> J[社区验证修复] J --> K[降低安全风险]4. 社区与生态系统A. DB-Engines 排名趋势MySQL 受欢迎度在 2024 年开始大幅下滑2026 年预计加速下跌B. 开发活跃度下降GitHub 提交量在 2025 年显著减少Oracle 于 2025 年 9 月大幅削减 MySQL 团队最新维护版本包含的 Bug 修复数量较之前减少C. 商业化压力Oracle 将用户推向闭源版本Heatwave 作为云专有服务推广MySQL 网站和文档引导用户远离开源版本Reddit 反馈显示用户被迫"付出更多获得更少"四、迁移选项分析1. MariaDB（推荐）A. 优势真正的开源项目由 MySQL 原作者 Michael "Monty" Widenius 创建高度向后兼容 MySQL开发透明，社区活跃大量应用已迁移B. 采用情况Wikipedia 等大型安装Fedora、Debian 等 Linux 发行版全球 57% 的 WordPress 网站使用 MariaDBMySQL 份额为 42%C. 迁移难度对于 LAMP 应用（WordPress、Drupal、Mediawiki、Nextcloud、Magento）直接替换现有连接器和数据库客户端无需修改Linux 发行版可通过简单命令安装：apt/dnf/brew install mariadb-server2. PostgreSQLA. 优势最流行的通用开源数据库功能丰富，社区强大高度可扩展B. 挑战从 MySQL 迁移需要大量工作架构差异显著需要重写 SQL 语句3. Percona ServerA. 优势紧密跟踪 MySQL 变更仅进行少量改进迁移简单B. 局限仍是 MySQL 定制版本未脱离 Oracle 依赖非长期解决方案4. TiDBA. 优势从头设计，高度可扩展与 MySQL 兼容适用于大型分布式系统Amazon DSQL 借鉴其设计B. 适用场景大型分布式设置需要高可扩展性的系统C. 挑战对于小型和中型应用可能过于复杂资源要求较高5. 迁移决策流程graph TD A[当前使用 MySQL] --> B{应用类型} B -->|LAMP 应用| C[选择 MariaDB] B -->|自定义应用| D{优先级} D -->|快速迁移| C D -->|长期独立| E{考虑因素} E -->|高性能/可扩展性/复制| C E -->|通用功能| F[PostgreSQL] E -->|分布式大型系统| G[TiDB] C --> H[安装: apt/dnf/brew install mariadb-server] F --> I[重写 SQL，调整应用] G --> J[评估资源需求]五、影响分析1. 行业影响A. 开源软件信任MySQL 案例凸显许可证与开发实践的区别GPL 许可证不保证真正的开源开发模式可能影响用户对 Oracle 管理的其他开源项目信任B. 数据库市场格局PostgreSQL 可能继续增长MariaDB 获得 MySQL 转移用户专用云数据库服务（如 Heatwave）与传统开源软件竞争2. 用户影响A. 现有 MySQL 用户需要评估迁移策略考虑长期支持和安全更新评估性能退化对业务的影响B. 新项目选择优先选择真正的开源数据库考虑社区活跃度和透明度评估长期可持续性C. 商业考量避免 Oracle 供应商锁定降低"付出更多获得更少"的风险保护数据主权和安全六、各方反应1. 专家观点A. Peter Zaitsev（Percona）2024 年 6 月发文《Oracle 终于要杀死 MySQL 吗》2025 年 11 月统计显示最新维护版本 Bug 修复减少对 MySQL 未来表示担忧B. Mark Callaghan（MySQL 性能专家）基准测试显示新版本性能退化MySQL 9.5 写密集型工作负载吞吐量下降 15%2. 社区反馈A. Reddit 讨论用户抱怨升级困难被迫为越来越少的功能支付更多费用对 Oracle 管理的 MySQL 失去信心B. 企业实践Amazon AWS 工程团队更倾向于贡献 MariaDB大型安装（如 Wikipedia）已迁移到 MariaDBLinux 发行版默认使用 MariaDB3. 技术趋势A. 开源定义讨论许可证 vs 开发实践透明度的重要性社区参与的价值B. 安全意识提升闭门开发的安全风险CVE 处理透明度的重要性供应商信任问题七、技术建议1. 评估当前使用审计所有 MySQL 实例评估迁移成本和风险确定迁移优先级2. 迁移规划选择目标数据库（推荐 MariaDB）制定详细迁移计划在测试环境验证准备回滚方案3. 长期策略投资真正的开源项目参与社区贡献避免供应商锁定保护数据主权参考资料Stop using MySQL in 2026, it is not true open source - Optimized by Otto
PentestOPS 渗透测试作业操作平台技术分析一、项目概述PentestOPS（又称 PentesterOPS Dashboard）是由开发者 Mohamed Nasr（GitHub 用户名 0xBugatti）构建的综合性渗透测试作业管理平台。该平台旨在为渗透测试团队提供完整的项目生命周期管理能力，涵盖从项目立项、任务分配、漏洞发现跟踪到客户资产管理的全套工作流程。项目采用现代 Web 技术栈构建，包括 Next.js 14 前端、Express 后端和 MongoDB 数据库，支持单容器 Docker 部署，显著降低了部署复杂度。项目于 2025 年以 MIT 开源许可证发布，源代码托管于 GitHub。图 1: PentestOPS 系统架构图二、核心技术架构2.1 技术栈组成前端技术栈技术组件版本用途Next.js14.0.4React 应用框架（App Router）React18.2.0UI 库TypeScript5.3.3类型安全TailwindCSS3.4.0原子化 CSS 框架Editor.js2.31.0富文本编辑器核心Zustand4.4.7轻量级状态管理React Query3.39.3服务端状态管理Axios1.6.2HTTP 客户端Framer Motion10.16.16动画库后端技术栈技术组件版本用途Node.js18+运行时环境Express4.18.2Web 应用框架TypeScript5.3.3类型安全MongoDB7.0NoSQL 数据库Mongoose8.0.3ODM（对象文档映射）JWT9.0.2身份认证Helmet7.1.0安全头设置Multer1.4.5文件上传处理2.2 系统架构设计PentestOPS 采用经典的三层架构模式：表现层：基于 Next.js 14 App Router 构建的单页应用，使用 React 组件化开发模式，通过 TailwindCSS 实现响应式设计，支持暗色主题。应用层：Express RESTful API 服务，负责业务逻辑处理、数据验证、权限控制和文件管理等核心功能。数据层：MongoDB 文档型数据库，通过 Mongoose ODM 进行数据建模和关系映射，支持灵活的文档结构。三、核心功能模块3.1 项目管理项目管理模块是 PentestOPS 的核心功能，支持渗透测试项目的全生命周期管理：多视图支持：提供看板视图（Kanban Board）、表格视图和卡片视图，满足不同场景下的信息浏览需求任务关联：每个项目可关联多个任务，支持任务的拖拽排序和状态流转资产管理：项目可关联目标资产信息，便于跟踪测试范围客户关联：支持将项目与客户信息绑定，便于客户关系管理团队协作：支持多用户协作，实现任务分配和进度跟踪3.2 任务管理系统任务管理模块提供了类似 Jira 的专业任务管理能力：多维度筛选：支持按状态、优先级、负责人等多维度筛选任务子任务支持：支持创建子任务，实现任务的层级化管理富文本描述：使用 Editor.js 编辑器支持标题、段落、代码块、表格、引用等多种格式评论系统：支持线程化评论，便于团队沟通和决策记录附件功能：支持上传 PDF、DOCX、XLSX、CSV、ZIP 及图片等文件3.3 漏洞发现跟踪漏洞管理模块整合了 CWE（Common Weakness Enumeration）数据库：CWE 映射：每个漏洞发现可关联到标准的 CWE 分类严重程度分级：支持按 CVSS 评分或自定义等级分类版本历史：记录漏洞信息的变更历史，支持差异查看和版本恢复证据附件：支持上传截图、POC 代码等证据文件状态跟踪：从发现到确认、修复、验证的完整状态流转3.4 富文本编辑能力PentestOPS 集成了功能强大的 Editor.js 编辑器，支持 Notion 风格的文档编辑：插件名称功能描述@editorjs/header多级标题@editorjs/list有序/无序列表@editorjs/checklist待办清单@editorjs/quote引用块@editorjs/code代码块@editorjs/table表格@editorjs/delimiter分隔线@editorjs/marker高亮标记@editorjs/inline-code行内代码@editorjs/link链接@editorjs/image图片3.5 全文搜索系统实现了全局搜索功能，支持跨以下实体的全文检索：项目（Projects）任务（Tasks）漏洞发现（Findings）客户（Clients）资产（Assets）页面/检查清单（Pages/Checklists）搜索采用 MongoDB 的文本索引功能，实现高效的关键词匹配。四、安全设计分析4.1 认证与授权PentestOPS 实现了基于 JWT（JSON Web Token）的双令牌认证机制：访问令牌（Access Token）：短期有效（通常 15 分钟），用于 API 访问认证刷新令牌（Refresh Token）：长期有效（通常 7 天），用于获取新的访问令牌密码存储：使用 bcryptjs 进行加盐哈希存储，哈希轮次为 10注册控制：通过 ALLOW_REGISTRATION 环境变量控制是否开放公开注册4.2 安全头设置后端通过 Helmet.js 中间件设置了一系列安全相关的 HTTP 响应头：// 内容安全策略 contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", "data:", "https:"], }, }4.3 速率限制生产环境启用了基于 IP 地址的速率限制：时间窗口：15 分钟最大请求数：100 次超限处理：返回 429 状态码4.4 CORS 配置系统支持灵活的跨域资源共享配置：开发环境：允许 localhost 和 127.0.0.1生产环境：通过 CORS_ORIGIN 环境变量配置允许的域名列表支持多域名配置（逗号分隔）4.5 容器安全Docker 容器采用了多项安全措施：非 root 用户运行：容器内使用 UID 1001 的 appuser 运行服务最小化镜像：生产镜像基于 node:18-slim，减少攻击面健康检查：内置健康检查机制，确保服务可用性资源限制：支持通过 Kubernetes 进行 CPU 和内存限制五、部署架构5.1 单容器部署模式PentestOPS 的特色之一是采用单容器部署模式，将 MongoDB、后端服务和前端构建产物打包到同一个 Docker 镜像中。优势分析：部署简化：无需管理多个容器和服务依赖资源优化：适用于小型团队和 VPS 部署启动顺序控制：通过 docker-entrypoint.sh 脚本确保服务按正确顺序启动技术实现：graph LR A[Dockerfile] --> B[Backend Build] A --> C[Frontend Build] B --> D[Production Image] C --> D D --> E[Runtime Container] E --> F[MongoDB] E --> G[Express API] E --> H[Next.js Server]5.2 容器启动流程docker-entrypoint.sh 脚本实现了以下启动流程：创建必要的目录结构检查文件系统权限启动 MongoDB 服务（后台运行）等待 MongoDB 就绪（最多 30 秒）初始化数据库创建默认管理员用户通过 PM2 启动后端和前端服务等待后端 API 健康检查通过输出服务访问信息5.3 进程管理系统使用 PM2（Process Manager 2）进行 Node.js 进程管理：// ecosystem.config.js 配置示例 { name: 'backend', script: 'dist/server.js', instances: 1, max_memory_restart: '500M', autorestart: true, watch: false }PM2 优势：自动重启：进程崩溃时自动重启内存监控：超过内存阈值时自动重启日志管理：统一的日志输出格式优雅关闭：支持 SIGTERM/SIGINT 信号处理5.4 Kubernetes 部署支持项目还提供了 Kubernetes 部署清单（k8s/deployment.yaml），支持在 K8s 集群中部署：Backend Deployment：2 副本，资源请求 256Mi/250mCPU，限制 512Mi/500mCPUFrontend Deployment：2 副本，相同资源配置Service 暴露：后端使用 ClusterIP，前端使用 LoadBalancerSecret 管理：敏感信息通过 K8s Secret 管理六、数据模型设计6.1 核心实体PentestOPS 的数据模型包含以下核心实体：用户（User）：用户名、邮箱、密码哈希角色和权限创建和更新时间戳项目（Project）：项目名称、描述、状态关联的客户和资产开始和结束日期项目成员任务（Task）：任务标题、描述、状态所属项目负责人优先级子任务列表关联附件漏洞发现（Finding）：漏洞标题、描述CWE 分类严重程度CVSS 评分状态（新建/确认/修复/验证）修复建议证据附件客户（Client）：客户名称、联系方式客户 Logo相关项目列表资产（Asset）：资产类型（域名/IP/应用）资产价值所属项目6.2 版本历史系统系统为重要实体实现了版本历史功能：每次创建或更新时自动创建版本快照支持查看任意两个版本之间的差异支持恢复到历史版本版本历史模型包含：关联实体的 ID 和类型版本号变更内容（完整 JSON）操作人时间戳七、技术特色与创新点7.1 单容器全栈方案在微服务架构盛行的今天，PentestOPS 选择了单容器部署方案，这是一种针对特定使用场景的务实选择：适用场景：小型渗透测试团队（5-20 人）资源受限的 VPS 环境快速部署和测试需求内网环境部署设计考量：MongoDB 仅监听 127.0.0.1，确保外部无法直接访问PM2 进程管理确保服务稳定性非root 用户运行降低容器逃逸风险7.2 Editor.js 深度集成富文本编辑器是渗透测试报告编写的关键工具，PentestOPS 对 Editor.js 的深度集成体现了对实际工作场景的理解：渗透测试场景需求：代码块高亮：用于展示 POC 代码表格支持：用于整理资产清单和测试结果检查清单：用于跟踪测试进度标题层级：支持结构化的报告编写截图上传：快速添加漏洞证据7.3 CWE 数据库集成将 CWE（Common Weakness Enumeration）数据库集成到漏洞管理中，体现了对安全标准化的重视：标准化漏洞分类：便于后续的统计分析和报告生成知识库链接：可直接关联到 MITRE CWE 官方文档行业对标：便于与行业数据进行对比八、潜在改进方向8.1 架构层面微服务化改造：对于大规模部署，可考虑将 MongoDB 独立部署缓存层引入：对于频繁查询的数据（如项目列表），可引入 Redis 缓存消息队列：对于耗时的操作（如报告生成），可引入异步任务队列全文搜索引擎：对于大型数据集，可考虑使用 Elasticsearch 替代 MongoDB 文本搜索8.2 功能层面报告生成：支持自动生成专业的渗透测试报告（PDF/Word）协作增强：引入 WebSocket 实现实时协作编辑移动端适配：开发移动端应用或响应式优化API 密钥管理：支持为第三方工具集成提供 API 密钥工作流引擎：支持自定义任务状态流转规则8.3 安全层面双因素认证：支持 TOTP 或 WebAuthn 2FA审计日志：记录所有敏感操作的详细日志数据加密：支持敏感数据的字段级加密RBAC 增强：实现更细粒度的权限控制九、部署实践指南9.1 快速部署（Docker）# 克隆仓库 git clone https://github.com/0xBugatti/PentestOPS.git cd PentestOPS # 构建镜像 docker build -t pentestops:latest . # 运行容器 docker run -d \ --name pentestops \ --restart unless-stopped \ -p 3000:3000 \ -p 4000:4000 \ -v pentestops-data:/data/db \ -v pentestops-uploads:/app/uploads \ -e JWT_SECRET=$(openssl rand -base64 32) \ -e JWT_REFRESH_SECRET=$(openssl rand -base64 32) \ -e NODE_ENV=production \ -e ALLOW_REGISTRATION=false \ pentestops:latest9.2 生产环境配置生产环境建议配置：反向代理：使用 Nginx 或 Caddy 作为反向代理HTTPS：通过 Let's Encrypt 获取 SSL 证书防火墙：仅开放 80/443 端口，内部服务不对外开放备份策略：定期备份 MongoDB 数据和上传文件监控告警：配置日志监控和性能监控十、总结PentestOPS 是一个功能全面、设计合理的渗透测试作业管理平台。它在以下方面表现突出：技术架构：采用成熟的全栈技术方案，代码结构清晰，易于维护和扩展用户体验：提供类似 Notion 的富文本编辑体验，支持多视图的任务管理部署便捷：单容器部署方案大幅降低了部署复杂度，适合快速上手安全设计：实现了 JWT 双令牌认证、速率限制、CORS 控制等安全措施开源生态：MIT 许可证鼓励社区贡献，适合二次开发和定制对于渗透测试团队而言，PentestOPS 提供了一个从零到一的完整解决方案，值得在团队协作场景中试用和评估。分析日期：2025年1月22日项目版本：基于 main 分支分析项目仓库：https://github.com/0xBugatti/PentestOPS作者：Mohamed Nasr (@0xBugatti)
Databasus 开源数据库备份工具技术分析一、背景与目标1. 项目背景A. 业务场景随着云计算和容器化技术的普及，数据库备份管理成为运维工作的核心环节。传统的备份方案存在以下痛点：需要编写复杂的脚本、缺乏统一的可视化管理界面、难以支持多种数据库类型、无法灵活配置存储目标和通知渠道。B. 痛点分析操作复杂：传统方案依赖命令行工具如 pg_dump、mysqldump，需要编写自动化脚本缺乏监控：备份任务执行状态难以及时掌握，失败发现滞后存储单一：难以同时支持本地存储和多种云存储服务协作困难：团队成员无法共享备份配置和查看备份历史2. 设计目标A. 功能目标支持 PostgreSQL、MySQL、MariaDB、MongoDB 四种主流数据库提供可视化的 Web 管理界面支持多种存储后端和通知渠道支持定时备份和加密B. 非功能目标安全性：备份文件 AES-256-GCM 加密，敏感数据不暴露易用性：提供直观的 UI，支持暗色/亮色主题可靠性：支持 Docker 容器化部署，自动重启可扩展性：支持团队协作，工作空间隔离，角色权限管理二、系统架构1. 整体架构graph TB subgraph 用户层 U1[管理员] U2[成员] U3[查看者] end subgraph Databasus应用层 W[Web界面] A[API服务] S[调度器] E[加密引擎] end subgraph 数据库连接层 PG[PostgreSQL] MY[MySQL] MR[MariaDB] MO[MongoDB] end subgraph 存储层 L[本地存储] S3[S3兼容存储] GD[Google Drive] FTP[SFTP/FTP] RC[Rclone] end subgraph 通知层 EM[邮件] TG[Telegram] SL[Slack] DC[Discord] WH[Webhook] end U1 --> W U2 --> W U3 --> W W --> A A --> S S --> PG S --> MY S --> MR S --> MO S --> E E --> L E --> S3 E --> GD E --> FTP E --> RC S --> EM S --> TG S --> SL S --> DC S --> WH2. 组件说明A. Web 界面提供 RESTful API 接口支持暗色和亮色主题切换响应式设计，支持移动端访问B. 调度器支持多种调度策略：每小时、每天、每周、每月、Cron 表达式智能压缩：4-8 倍空间节省，约 20% 性能开销C. 加密引擎使用 AES-256-GCM 算法加密备份文件零信任存储：加密后的备份文件即使泄露也无法解密敏感数据加密存储，日志中不暴露三、核心功能1. 支持的数据库数据库类型支持版本PostgreSQL12, 13, 14, 15, 16, 17, 18MySQL5.7, 8, 9MariaDB10, 11MongoDB4, 5, 6, 7, 82. 定时备份策略graph LR A[调度器] --> B{调度类型} B --> C[每小时] B --> D[每天] B --> E[每周] B --> F[每月] B --> G[Cron表达式] C --> H[执行备份] D --> H E --> H F --> H G --> H H --> I[压缩] I --> J[加密] J --> K[存储] K --> L[通知]3. 存储后端支持本地存储：直接存储在服务器磁盘云存储：S3、Cloudflare R2、Google Drive、Azure Blob Storage网络存储：NAS、SFTP、FTP扩展存储：通过 Rclone 支持 70+ 种存储服务4. 通知渠道邮件：SMTP 协议即时通讯：Telegram、Slack、DiscordWebhook：自定义 HTTP 回调四、安全设计1. 加密机制A. 备份文件加密算法：AES-256-GCM适用场景：所有存储到外部服务的备份文件安全性：即使存储服务被攻破，备份文件也无法解密B. 敏感数据保护数据库凭证加密存储敏感配置不在日志中显示错误信息中不包含敏感数据2. 访问控制A. 工作空间隔离不同项目/团队使用独立工作空间工作空间间数据隔离B. 角色权限角色权限查看者仅查看备份状态和历史成员管理数据库和备份任务管理员管理工作空间内所有资源所有者完全控制，包括删除工作空间C. 审计日志记录所有用户操作记录备份任务执行历史3. 只读用户原则Databasus 默认使用只读用户连接数据库不存储任何可以修改数据的凭证备份过程不会对源数据库产生写入操作五、部署方式1. 部署架构对比graph LR subgraph Docker部署 D1[Docker Run] D2[Docker Compose] end subgraph K8s部署 K1[ClusterIP] K2[LoadBalancer] K3[Ingress] end D1 --> S[Databasus容器] D2 --> S K1 --> S K2 --> S K3 --> S S --> V[数据卷 ./databasus-data]2. 自动化脚本部署（推荐）sudo apt-get install -y curl && \ sudo curl -sSL https://raw.githubusercontent.com/databasus/databasus/refs/heads/main/install-databasus.sh \ | sudo bash功能：自动安装 Docker 和 Docker Compose配置 Databasus 服务设置开机自启动3. Docker Run 部署docker run -d \ --name databasus \ -p 4005:4005 \ -v ./databasus-data:/databasus-data \ --restart unless-stopped \ databasus/databasus:latest4. Docker Compose 部署services: databasus: container_name: databasus image: databasus/databasus:latest ports: - "4005:4005" volumes: - ./databasus-data:/databasus-data restart: unless-stopped5. Kubernetes Helm 部署A. ClusterIP + Port-Forward（开发/测试）helm install databasus oci://ghcr.io/databasus/charts/databasus \ -n databasus --create-namespace kubectl port-forward svc/databasus-service 4005:4005 -n databasusB. LoadBalancer（云环境）helm install databasus oci://ghcr.io/databasus/charts/databasus \ -n databasus --create-namespace \ --set service.type=LoadBalancerC. Ingress（域名访问）helm install databasus oci://ghcr.io/databasus/charts/databasus \ -n databasus --create-namespace \ --set ingress.enabled=true \ --set ingress.hosts[0].host=backup.example.com六、使用流程graph TD A[访问 Dashboard http://localhost:4005] --> B[添加数据库] B --> C[配置调度策略] C --> D[设置数据库连接] D --> E[选择存储后端] E --> F{添加通知?} F -->|是| G[配置通知渠道] F -->|否| H[保存并启动] G --> H H --> I[系统验证配置] I --> J{验证成功?} J -->|是| K[开始定时备份] J -->|否| L[修正配置] L --> I K --> M[接收备份通知]七、技术特点1. 从 Postgresus 到 Databasus项目原名为 Postgresus，专注于 PostgreSQL 备份。2025 年 12 月更名为 Databasus，主要原因是：功能扩展：从单一 PostgreSQL 支持扩展到 MySQL、MariaDB、MongoDB品牌定位：从简单的 pg_dump UI 包装工具成长为成熟的备份管理系统商标合规：PostgreSQL 是 PostgreSQL Inc. 的注册商标2. 云数据库与自托管数据库支持A. 支持的云数据库AWS RDSGoogle Cloud SQLAzure DatabaseB. 不支持 PITR 的原因云提供商已提供原生的 PITR（时间点恢复）功能，外部 PITR 备份无法恢复到托管的云数据库，因此对云托管 PostgreSQL 来说不实用。C. 实用的备份粒度每小时和每日备份对 99% 的项目已足够，无需 WAL 归档的操作复杂性。3. AI 辅助开发策略A. AI 用于代码质量验证和漏洞搜索文档、注释和代码清理改进开发过程中的辅助人工审查后的 PR 和提交双重检查B. AI 不用于编写整个代码随意编写代码未经人工逐行验证的代码没有测试的代码C. 质量保证完善的测试覆盖率（单元测试和集成测试）CI/CD 流水线自动化经验丰富的开发者验证八、对比分析1. 与传统备份方案对比特性Databasus传统脚本方案部署复杂度低（Docker 一键部署）高（需编写和维护脚本）可视化管理支持不支持多数据库支持支持需分别配置存储后端多种通常单一通知渠道多种需自行实现加密支持内置 AES-256-GCM需自行实现团队协作支持不支持2. 与云备份服务对比特性Databasus云备份服务数据主权完全控制托管给云服务商成本一次性部署成本按量计费定制性高（开源可修改）低混合云支持支持通常受限九、适用场景1. 推荐使用场景中小企业：缺乏专业 DBA 团队，需要简单可靠的备份方案DevOps 团队：需要可视化的备份管理界面多数据库环境：同时使用 PostgreSQL、MySQL、MongoDB混合云部署：数据库分布在本地和云端合规要求高：需要数据加密和审计日志2. 不适用场景需要 PITR 的 PostgreSQL：云数据库已有原生 PITR超大规模部署：单一实例可能有性能瓶颈特殊数据库：不支持除四种外的其他数据库十、总结Databasus 是一个设计精良的开源数据库备份管理工具，通过 Docker 容器化部署和友好的 Web 界面，大大降低了数据库备份管理的门槛。其核心优势在于：多数据库支持：覆盖 PostgreSQL、MySQL、MariaDB、MongoDB 四种主流数据库安全可靠：AES-256-GCM 加密、零信任存储、只读用户原则易于部署：支持自动化脚本、Docker、Kubernetes 多种部署方式团队协作：工作空间隔离、角色权限、审计日志灵活通知：邮件、Telegram、Slack、Discord、Webhook 多渠道对于需要统一管理多种数据库备份的团队，Databasus 是一个值得考虑的自托管解决方案。参考资料Databasus GitHub Repository
Redis NUMA 架构下的延迟性能优化案例分析一、事件概述1. 事件背景Redis 作为核心存储组件，对实时性要求非常高。在长期运行后，Redis 服务会出现性能下降，导致较大的查询延迟，拖慢整个链路的响应速度。2. 影响范围A. 影响功能Redis 数据库的所有查询操作B. 性能指标P99 延迟从 9.2ms 降至 5.7ms，下降约 37%3. 严重程度P2 级性能问题（核心业务响应速度受影响）二、问题分析1. 直接原因通过 HUATUO 系统观测指标分析，发现 Redis 延迟升高时，NUMA 页面迁移指标（huatuo_bamai_vmstat_numa_pages_migrated）同步升高，两者趋势一致。2. 根本原因（5 Whys 分析）A. 为什么出现这个问题？Redis 进程在 NUMA 架构下，内存分散在不同的内存节点上，访问远端节点内存时触发 NUMA balancing，导致页面迁移，在 page fault 中产生额外开销。B. 为什么内存会分散？负载变化导致 Redis 进程在 node 之间迁移AOF 备份产生的文件缓存持续占用内存，导致某个 node 可用内存减少，后续分配从另一个 node 进行C. 为什么没有自动优化？内核默认的 NUMA balancing 策略旨在提高访存速度，但对内存带宽敏感型的数据库服务，页面迁移本身的开销超过了收益。3. 深层反思容器化环境下，NUMA 架构与内存管理策略需要针对不同类型的负载进行调优，通用内核参数无法满足所有场景。三、问题定位过程1. 观测指标使用 HUATUO 提供的关键指标：huatuo_bamai_vmstat_numa_pages_migrated：系统级 NUMA 页面迁移次数huatuo_bamai_vmstat_container_numa_pages_migrated：容器级 NUMA 页面迁移次数nr_inactive_file：非活跃文件缓存页数nr_active_file：活跃文件缓存页数nr_free_pages：空闲内存页数2. 指标关联分析graph TD A[Redis 延迟升高] --> B[NUMA 页面迁移指标升高] B --> C[发现关联性] C --> D[AOF 操作] D --> E[nr_inactive_file 升高] E --> F[nr_active_file 升高] F --> G[nr_free_pages 下降] G --> H[跨 node 内存分配] H --> I[NUMA balancing 触发] I --> J[页面迁移开销] J --> A3. 现象总结触发 NUMA balancing 的两个条件：A. 进程迁移随着负载变化，Redis 进程会在 node 之间迁移，导致内存分散在两个内存节点上。B. 文件缓存占用Redis 定期进行数据备份（AOF），将数据保存在文件里。这些磁盘数据写完后一般不再使用，但仍留在文件缓存中，导致某个 node 可用内存特别少。四、解决方案1. 临时方案A. 提升内存水位参数将 vm.watermark_scale_factor 设定为 1000，使内核的 low 水位被设定为总内存的 1/10。B. 效果评估kswapd 可以频繁回收文件缓存，让 free 内存保持合理水平，内存分配不会被迫横跨节点，NUMA miss 减少到接近 0。2. 永久方案A. 提升内存水位调整 vm.watermark_scale_factor 参数B. 关闭 NUMA balancing对于内存带宽敏感型的数据库服务，关闭 NUMA balance 策略C. 实施计划测试环境验证参数调整效果生产环境分批次灰度调整五、技术细节1. vm.watermark_scale_factor 参数详解A. 参数作用控制内存水位的间距，影响内核的内存回收行为，主要是 kswapd 守护进程的唤醒和睡眠时机。B. 参数特性不改变 min 水位只影响 min 水位到 low 和 high 的间距默认值为 10（对应总内存的 0.1%）取值范围为 0-3000（即 0% 到 30%）C. 计算公式WMARK_LOW = WMARK_MIN + (zone->managed_pages * vm_watermark_scale_factor) / 10000 WMARK_HIGH = WMARK_LOW + (zone->managed_pages * vm_watermark_scale_factor) / 10000D. 推荐配置vm.watermark_scale_factor=10002. NUMA balancing 策略A. 工作原理NUMA balance 调度策略会在进程尝试访问远端 NUMA node 内存时，把远端 NUMA node 上的内容复制到本地，目的是提高访存速度。B. 适用场景通用计算负载，访存局部性较好的应用C. 不适用场景数据库或内存带宽敏感型服务D. 关闭方法echo 0 > /proc/sys/kernel/numa_balancing # 或者在内核启动参数中添加 numa_balancing=0六、优化效果1. 集群 A 调整结果A. 调整内容调整业务集群 A 宿主机参数 vm.watermark_scale_factor=1000B. 性能提升周五晚高峰 P99 均值从 9.2ms 降为 5.7ms，下降约 37%2. 集群 B 调整结果A. 调整内容关闭 NUMA balance 策略B. 性能提升P99 耗时有明显下降3. 综合评估通过内核参数调优和 NUMA 策略调整，业务层面的延迟整体降低 30% 以上。七、内存回收机制1. 内存水位管理graph LR A[内存使用] --> B{低于 min 水位} B -->|是| C[同步回收] B -->|否| D{低于 low 水位} D -->|是| E[kswapd 后台回收] D -->|否| F{低于 high 水位} F -->|是| G[kswapd 继续回收] F -->|否| H[停止回收]2. kswapd 工作流程监控内存水位低于 low 水位时唤醒回收文件缓存和匿名内存达到 high 水位时休眠3. watermark_scale_factor 影响增大该参数会扩大 low 和 high 水位之间的差距，使 kswapd 更早开始回收，更激进地释放内存。八、经验总结1. 做得好的地方使用系统可观测性工具（HUATUO）进行根因定位从指标关联分析到问题定位的逻辑清晰方案实施前后有明确的性能对比2. 需要改进的地方容器环境下的 NUMA 感知调度需要更多优化AOF 备份产生的文件缓存应该主动清理3. 流程优化建议建立数据库类服务的内核参数基线NUMA 架构服务器上的服务部署规范定期检查 NUMA 页面迁移指标九、最佳实践1. 数据库类服务内核参数推荐# 提升内存水位，激进回收文件缓存 vm.watermark_scale_factor=1000 # 关闭 NUMA balancing kernel.numa_balancing=0 # 调整 vm.dirty_ratio，控制脏页比例 vm.dirty_ratio=10 vm.dirty_background_ratio=52. Redis 部署建议A. 绑定 CPU 核心使用 taskset 或 cset 将 Redis 进程绑定到特定 CPU 核心B. 绑定 NUMA 节点使用 numactl 将 Redis 进程绑定到特定 NUMA 节点C. AOF 配置优化# AOF 文件路径放在独立磁盘 # 定期压缩 AOF 文件 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb3. 监控指标A. 关键指标NUMA 页面迁移次数跨节点内存访问次数内存使用分布kswapd 回收频率B. 告警规则NUMA 页面迁移次数突增P99 延迟超过基线 20%跨节点内存分配比例超过 10%参考资料延迟降低30%! redis 延迟性能问题分析Redis 延迟问题全面排障指南Redis 实战：延迟问题排障指南
MySQL主从复制搭建实战：数据同步零丢失配置指南
MySQL主从复制搭建实战：数据同步零丢失配置指南一、概述1. 背景介绍在生产环境中运维MySQL数据库十年，主从复制是遇到最频繁的架构需求之一。无论是为了读写分离提升性能，还是为了数据容灾保障业务连续性，主从复制都是MySQL高可用架构的基石。2019年的一次惨痛经历至今记忆犹新：某电商平台大促期间，单机MySQL扛不住流量直接宕机，由于没有从库，数据恢复花了整整6个小时，直接损失数百万。这次事故之后，主从复制成为所有核心业务数据库的标配。A. 核心原理MySQL主从复制的核心原理是：主库将数据变更写入二进制日志（Binary Log），从库通过I/O线程读取主库的binlog并写入本地的中继日志（Relay Log），然后SQL线程读取中继日志并在从库上重放这些变更，从而实现数据同步。2. 技术特点MySQL 8.0/8.4 LTS版本在复制功能上有了重大改进：A. 基于GTID的复制全局事务标识符（GTID）让每个事务都有唯一标识故障切换时自动定位复制位点，无需手动指定binlog文件和位置支持自动故障转移，大幅简化运维复杂度B. 增强的半同步复制主库提交事务前必须收到至少一个从库的确认配合rpl_semi_sync_source_wait_for_replica_count参数可要求多个从库确认有效防止主库故障时的数据丢失C. 并行复制优化基于WriteSet的并行复制，大幅提升从库回放效率replica_parallel_type=LOGICAL_CLOCK配合binlog_transaction_dependency_tracking=WRITESET实测可将复制延迟从分钟级降到秒级D. 克隆插件支持MySQL 8.0.17+引入Clone Plugin从库初始化无需mysqldump或xtrabackup自动完成数据同步和复制配置3. 适用场景场景说明推荐配置读写分离主库写、从库读，分担主库压力异步复制 + 多从库数据容灾主库故障时快速切换到从库半同步复制 + GTID数据备份在从库执行备份，不影响主库性能异步复制 + 延迟从库数据分析报表查询在从库执行异步复制 + 专用从库跨地域部署多数据中心数据同步异步复制 + 压缩传输4. 环境要求组件版本要求说明MySQL Server8.0.35+ 或 8.4 LTS推荐使用8.4 LTS长期支持版本操作系统Rocky 9 / Ubuntu 24.04内核版本5.14+内存最低4GB，推荐16GB+InnoDB Buffer Pool需要足够内存磁盘SSD，IOPS 3000+binlog和数据文件分盘存储网络主从之间延迟<1ms同机房部署最佳本文实验环境：主库：192.168.1.100（master.example.com）从库：192.168.1.101（slave.example.com）系统：Rocky Linux 9.3MySQL：8.4.0 LTS二、准备工作1. 系统环境配置在主库和从库服务器上执行相同的系统配置：# 关闭SELinux（或配置相应策略） sudo setenforce 0 sudo sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config # 配置防火墙 sudo firewall-cmd --permanent --add-port=3306/tcp sudo firewall-cmd --reload # 配置时间同步（主从时间必须一致） sudo dnf install -y chrony sudo systemctl enable --now chronyd # 验证时间同步状态 chronyc tracking # 配置主机名解析 echo "192.168.1.100 master.example.com master" | sudo tee -a /etc/hosts echo "192.168.1.101 slave.example.com slave" | sudo tee -a /etc/hosts # 优化系统参数 cat << 'EOF' | sudo tee /etc/sysctl.d/mysql.conf # 网络优化 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_keepalive_time = 600 # 内存优化 vm.swappiness = 1 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5 # 文件描述符 fs.file-max = 6815744 fs.aio-max-nr = 1048576 EOF sudo sysctl -p /etc/sysctl.d/mysql.conf # 配置用户资源限制 cat << 'EOF' | sudo tee /etc/security/limits.d/mysql.conf mysql soft nofile 65535 mysql hard nofile 65535 mysql soft nproc 65535 mysql hard nproc 65535 EOF2. 安装MySQL 8.4 LTS# 添加MySQL官方仓库 sudo dnf install -y https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm # 安装MySQL Server sudo dnf install -y mysql-community-server mysql-community-client # 查看安装版本 mysql --version # mysql Ver 8.4.0 for Linux on x86_64 (MySQL Community Server - GPL) # 创建数据目录（建议数据和日志分盘） sudo mkdir -p /data/mysql/{data,logs,binlog,relaylog,tmp} sudo chown -R mysql:mysql /data/mysql sudo chmod 750 /data/mysql3. 生成server-idMySQL主从复制要求每个节点有唯一的server-id。推荐使用IP地址最后两段作为server-id：# 主库（192.168.1.100） # server-id = 1100 # 从库（192.168.1.101） # server-id = 1101三、核心配置1. 主库配置创建主库配置文件 /etc/my.cnf：[mysqld] # 基础配置 user = mysql port = 3306 basedir = /usr datadir = /data/mysql/data tmpdir = /data/mysql/tmp socket = /var/lib/mysql/mysql.sock pid-file = /var/run/mysqld/mysqld.pid # 字符集配置 character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' # 主从复制核心配置 server-id = 1100 log-bin = /data/mysql/binlog/mysql-bin binlog_format = ROW binlog_row_image = FULL max_binlog_size = 1G binlog_expire_logs_seconds = 604800 sync_binlog = 1 # GTID配置（强烈推荐） gtid_mode = ON enforce_gtid_consistency = ON binlog_gtid_simple_recovery = ON # 半同步复制配置 # MySQL 8.0.26+使用新参数名 rpl_semi_sync_source_enabled = ON rpl_semi_sync_source_timeout = 10000 rpl_semi_sync_source_wait_for_replica_count = 1 rpl_semi_sync_source_wait_point = AFTER_SYNC # InnoDB配置 innodb_buffer_pool_size = 8G innodb_buffer_pool_instances = 8 innodb_log_file_size = 2G innodb_log_buffer_size = 64M innodb_flush_log_at_trx_commit = 1 innodb_flush_method = O_DIRECT innodb_file_per_table = ON innodb_io_capacity = 4000 innodb_io_capacity_max = 8000 innodb_read_io_threads = 8 innodb_write_io_threads = 8 # 连接配置 max_connections = 2000 max_connect_errors = 100000 wait_timeout = 600 interactive_timeout = 600 # 日志配置 log_error = /data/mysql/logs/error.log slow_query_log = ON slow_query_log_file = /data/mysql/logs/slow.log long_query_time = 1 log_queries_not_using_indexes = ON # 性能优化 table_open_cache = 4000 table_definition_cache = 2000 thread_cache_size = 128 sort_buffer_size = 4M join_buffer_size = 4M read_buffer_size = 2M read_rnd_buffer_size = 8M # 安全配置 local_infile = OFF skip_symbolic_links = ON sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION [client] socket = /var/lib/mysql/mysql.sock default-character-set = utf8mb4 [mysql] socket = /var/lib/mysql/mysql.sock default-character-set = utf8mb4 prompt = "\\u@\\h [\\d]> "2. 从库配置创建从库配置文件 /etc/my.cnf：[mysqld] # 基础配置 user = mysql port = 3306 basedir = /usr datadir = /data/mysql/data tmpdir = /data/mysql/tmp socket = /var/lib/mysql/mysql.sock pid-file = /var/run/mysqld/mysqld.pid # 字符集配置 character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' # 主从复制核心配置 server-id = 1101 log-bin = /data/mysql/binlog/mysql-bin binlog_format = ROW binlog_row_image = FULL max_binlog_size = 1G binlog_expire_logs_seconds = 604800 sync_binlog = 1 # 从库开启binlog（用于级联复制或切换为主库） log_replica_updates = ON # 中继日志配置 relay_log = /data/mysql/relaylog/relay-bin relay_log_recovery = ON relay_log_info_repository = TABLE relay_log_purge = ON # GTID配置 gtid_mode = ON enforce_gtid_consistency = ON binlog_gtid_simple_recovery = ON # 半同步复制配置（从库端） rpl_semi_sync_replica_enabled = ON # 并行复制配置（大幅降低复制延迟） replica_parallel_type = LOGICAL_CLOCK replica_parallel_workers = 16 replica_preserve_commit_order = ON binlog_transaction_dependency_tracking = WRITESET transaction_write_set_extraction = XXHASH64 # 复制过滤（按需配置） # replicate_do_db = app_db # replicate_ignore_db = test # replicate_wild_do_table = app_%.% # replicate_wild_ignore_table = %.tmp_% # 从库只读配置 read_only = ON super_read_only = ON # InnoDB配置 innodb_buffer_pool_size = 8G innodb_buffer_pool_instances = 8 innodb_log_file_size = 2G innodb_log_buffer_size = 64M innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT innodb_file_per_table = ON innodb_io_capacity = 4000 innodb_io_capacity_max = 8000 innodb_read_io_threads = 8 innodb_write_io_threads = 8 # 连接配置 max_connections = 2000 max_connect_errors = 100000 wait_timeout = 600 interactive_timeout = 600 # 日志配置 log_error = /data/mysql/logs/error.log slow_query_log = ON slow_query_log_file = /data/mysql/logs/slow.log long_query_time = 1 log_queries_not_using_indexes = ON # 性能优化 table_open_cache = 4000 table_definition_cache = 2000 thread_cache_size = 128 sort_buffer_size = 4M join_buffer_size = 4M read_buffer_size = 2M read_rnd_buffer_size = 8M # 安全配置 local_infile = OFF skip_symbolic_links = ON sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION [client] socket = /var/lib/mysql/mysql.sock default-character-set = utf8mb4 [mysql] socket = /var/lib/mysql/mysql.sock default-character-set = utf8mb4 prompt = "\\u@\\h [\\d]> "四、启动和验证1. 初始化并启动主库# 初始化数据目录 sudo mysqld --initialize --user=mysql --datadir=/data/mysql/data # 获取临时密码 sudo grep 'temporary password' /data/mysql/logs/error.log # 2024-01-15T10:30:45.123456Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: Abc123!@#xyz # 启动MySQL服务 sudo systemctl start mysqld sudo systemctl enable mysqld # 修改root密码并进行安全配置 mysql -uroot -p'Abc123!@#xyz' --connect-expired-password << 'EOF' ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPassword@2024'; DELETE FROM mysql.user WHERE User=''; DROP DATABASE IF EXISTS test; DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%'; FLUSH PRIVILEGES; EOF # 安装半同步复制插件 mysql -uroot -p'YourStrongPassword@2024' << 'EOF' INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so'; SET GLOBAL rpl_semi_sync_source_enabled = ON; SHOW PLUGINS WHERE Name LIKE '%semi%'; EOF2. 创建复制用户在主库上创建专用的复制用户：-- 登录主库 mysql -uroot -p'YourStrongPassword@2024' -- 创建复制用户 CREATE USER 'repl_user'@'192.168.1.%' IDENTIFIED WITH caching_sha2_password BY 'ReplPassword@2024'; -- 授予复制权限 GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl_user'@'192.168.1.%'; -- 如果使用Clone插件初始化从库，还需要额外权限 GRANT BACKUP_ADMIN ON *.* TO 'repl_user'@'192.168.1.%'; FLUSH PRIVILEGES; -- 查看主库状态 SHOW MASTER STATUS\G /* *************************** 1. row *************************** File: mysql-bin.000003 Position: 856 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 3e11fa47-c5ab-11ee-9c88-000c29123456:1-15 */ -- 查看GTID执行状态 SELECT @@GLOBAL.GTID_EXECUTED;3. 初始化并启动从库A. 方法一：使用Clone插件（推荐，MySQL 8.0.17+）# 从库执行初始化（空数据目录） sudo mysqld --initialize --user=mysql --datadir=/data/mysql/data # 获取临时密码并启动 sudo grep 'temporary password' /data/mysql/logs/error.log sudo systemctl start mysqld # 修改root密码 mysql -uroot -p'临时密码' --connect-expired-password << 'EOF' ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPassword@2024'; EOF-- 登录从库 mysql -uroot -p'YourStrongPassword@2024' -- 安装Clone插件 INSTALL PLUGIN clone SONAME 'mysql_clone.so'; -- 配置克隆源（主库地址） SET GLOBAL clone_valid_donor_list = '192.168.1.100:3306'; -- 执行克隆操作（会覆盖从库所有数据并重启） CLONE INSTANCE FROM 'repl_user'@'192.168.1.100':3306 IDENTIFIED BY 'ReplPassword@2024'; -- 克隆完成后MySQL会自动重启，重新登录 mysql -uroot -p'YourStrongPassword@2024' -- 安装半同步复制插件 INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so'; SET GLOBAL rpl_semi_sync_replica_enabled = ON;B. 方法二：使用mysqldump（适合小型数据库）# 在主库执行导出 mysqldump -uroot -p'YourStrongPassword@2024' \ --all-databases \ --single-transaction \ --routines \ --triggers \ --events \ --set-gtid-purged=ON \ --source-data=2 \ > /tmp/full_backup.sql # 传输到从库 scp /tmp/full_backup.sql slave:/tmp/ # 在从库导入 mysql -uroot -p'YourStrongPassword@2024' < /tmp/full_backup.sql4. 配置从库复制-- 登录从库 mysql -uroot -p'YourStrongPassword@2024' -- 配置复制（使用GTID模式） CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.100', SOURCE_PORT = 3306, SOURCE_USER = 'repl_user', SOURCE_PASSWORD = 'ReplPassword@2024', SOURCE_AUTO_POSITION = 1, SOURCE_CONNECT_RETRY = 10, SOURCE_RETRY_COUNT = 3, GET_SOURCE_PUBLIC_KEY = 1; -- 启动复制 START REPLICA; -- 查看复制状态 SHOW REPLICA STATUS\G5. 验证复制状态-- 在从库执行，检查关键指标 SHOW REPLICA STATUS\G /* 关键字段说明： Replica_IO_Running: Yes -- I/O线程运行状态 Replica_SQL_Running: Yes -- SQL线程运行状态 Seconds_Behind_Source: 0 -- 复制延迟（秒） Retrieved_Gtid_Set: ... -- 已接收的GTID集合 Executed_Gtid_Set: ... -- 已执行的GTID集合 Auto_Position: 1 -- GTID自动定位 Source_SSL_Allowed: Yes -- SSL状态 */ -- 检查半同步状态（主库） SHOW STATUS LIKE 'Rpl_semi_sync%'; /* Rpl_semi_sync_source_status | ON Rpl_semi_sync_source_clients | 1 Rpl_semi_sync_source_yes_tx | 156 Rpl_semi_sync_source_no_tx | 0 */ -- 检查半同步状态（从库） SHOW STATUS LIKE 'Rpl_semi_sync%'; /* Rpl_semi_sync_replica_status | ON */6. 测试数据同步-- 主库创建测试数据 CREATE DATABASE test_repl; USE test_repl; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB; INSERT INTO users (username, email) VALUES ('user1', 'user1@example.com'), ('user2', 'user2@example.com'), ('user3', 'user3@example.com'); -- 从库验证数据 USE test_repl; SELECT * FROM users; /* +----+----------+-------------------+---------------------+ | id | username | email | created_at | +----+----------+-------------------+---------------------+ | 1 | user1 | user1@example.com | 2024-01-15 10:45:30 | | 2 | user2 | user2@example.com | 2024-01-15 10:45:30 | | 3 | user3 | user2@example.com | 2024-01-15 10:45:30 | +----+----------+-------------------+---------------------+ */五、架构模式1. 一主多从架构生产环境中常见的一主多从架构，通常配置2-3个从库分担读压力：graph TD M[Master 192.168.1.100] --> S1[Slave1 192.168.1.101 读请求] M --> S2[Slave2 192.168.1.102 读请求] M --> S3[Slave3 192.168.1.103 备份专用]从库1和从库2的配置基本相同，从库3作为备份专用，可配置为延迟从库：# 从库3配置（延迟复制，用于误操作恢复） [mysqld] # ...其他配置同上... # 延迟复制配置：延迟1小时 # 在CHANGE REPLICATION SOURCE时指定 # SOURCE_DELAY = 3600配置延迟从库：CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.100', SOURCE_PORT = 3306, SOURCE_USER = 'repl_user', SOURCE_PASSWORD = 'ReplPassword@2024', SOURCE_AUTO_POSITION = 1, SOURCE_DELAY = 3600; -- 延迟1小时 START REPLICA;2. 级联复制架构当从库数量较多时，可采用级联复制减轻主库压力：graph TD M[Master 192.168.1.100] --> RS[Relay Slave 192.168.1.101] RS --> S2[Slave2 192.168.1.102] RS --> S3[Slave3 192.168.1.103]中继从库配置要点：# 中继从库关键配置 [mysqld] server-id = 1101 log-bin = /data/mysql/binlog/mysql-bin # 必须开启此选项，将接收到的事务写入自己的binlog log_replica_updates = ON # 其他配置同普通从库六、实际应用案例1. 电商平台读写分离某电商平台日活百万，订单系统数据库面临高并发压力。A. 需求分析写入QPS：约500读取QPS：约5000数据量：200GB可用性要求：99.99%B. 架构设计sequenceDiagram participant App as 应用服务器 participant M as 主库 写操作 participant S1 as 从库1 读操作 participant S2 as 从库2 读操作 App->>M: 写入订单 M-->>App: 写入成功 App->>S1: 查询订单 S1-->>App: 返回数据 App->>S2: 统计报表 S2-->>App: 返回结果C. 应用层配置示例（Python + SQLAlchemy）from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker import random class MySQLRouter: """MySQL主从路由器""" def __init__(self): # 主库连接（写操作） self.master = create_engine( 'mysql+pymysql://app_user:password@192.168.1.100:3306/order_db', pool_size=20, max_overflow=10, pool_pre_ping=True, pool_recycle=3600 ) # 从库连接池（读操作） self.slaves = [ create_engine( 'mysql+pymysql://app_user:password@192.168.1.101:3306/order_db', pool_size=30, max_overflow=20, pool_pre_ping=True, pool_recycle=3600 ), create_engine( 'mysql+pymysql://app_user:password@192.168.1.102:3306/order_db', pool_size=30, max_overflow=20, pool_pre_ping=True, pool_recycle=3600 ) ] def get_read_connection(self): """获取读连接（负载均衡）""" return random.choice(self.slaves) def get_write_connection(self): """获取写连接""" return self.master # 使用示例 router = MySQLRouter() # 写操作 with router.get_write_connection().connect() as conn: conn.execute(text("INSERT INTO orders (user_id, amount) VALUES (:uid, :amt)"), {"uid": 1001, "amt": 99.99}) conn.commit() # 读操作 with router.get_read_connection().connect() as conn: result = conn.execute(text("SELECT * FROM orders WHERE user_id = :uid"), {"uid": 1001}) orders = result.fetchall()2. 跨机房容灾部署某金融系统要求同城双活，异地灾备：graph LR subgraph 北京机房 M[Master 192.168.1.100] --> SS[Sync Slave 半同步复制] end subgraph 上海机房 M -->|异步复制 30ms| DR[DR Slave 192.168.2.100] end异地从库特殊配置：# 异地从库配置 [mysqld] server-id = 2100 # 压缩传输减少带宽消耗 replica_compressed_protocol = ON # 适当增大超时时间（跨机房网络延迟） replica_net_timeout = 120 # 增大中继日志空间 relay_log_space_limit = 20G # 允许较大的复制延迟 # 通过监控而非配置限制七、最佳实践1. 性能优化A. 并行复制调优MySQL 8.0的并行复制能显著降低复制延迟，关键参数调优：-- 查看当前并行复制配置 SHOW VARIABLES LIKE '%replica_parallel%'; SHOW VARIABLES LIKE '%binlog_transaction_dependency%'; -- 推荐配置（从库执行） SET GLOBAL replica_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL replica_parallel_workers = 16; -- 通常设为CPU核数 SET GLOBAL replica_preserve_commit_order = ON; SET GLOBAL binlog_transaction_dependency_tracking = 'WRITESET'; -- 监控并行复制效果 SELECT * FROM performance_schema.replication_applier_status_by_worker;B. 网络传输优化# 主库配置 [mysqld] # 增大binlog缓存 binlog_cache_size = 4M binlog_stmt_cache_size = 4M # 批量发送优化 replica_net_timeout = 60# 从库配置（跨机房时启用） [mysqld] # 启用压缩传输 replica_compressed_protocol = ON2. 安全加固A. 网络安全-- 复制用户仅允许特定IP段访问 CREATE USER 'repl_user'@'192.168.1.0/255.255.255.0' IDENTIFIED WITH caching_sha2_password BY 'StrongPassword@2024' REQUIRE SSL; -- 强制SSL连接 GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.0/255.255.255.0';B. SSL加密复制# 生成SSL证书 mkdir -p /etc/mysql/ssl cd /etc/mysql/ssl # CA证书 openssl genrsa 2048 > ca-key.pem openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca-cert.pem \ -subj "/C=CN/ST=Beijing/L=Beijing/O=Example/CN=MySQL-CA" # 主库证书 openssl req -newkey rsa:2048 -nodes -keyout master-key.pem -out master-req.pem \ -subj "/C=CN/ST=Beijing/L=Beijing/O=Example/CN=master.example.com" openssl x509 -req -in master-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem \ -set_serial 01 -out master-cert.pem # 从库证书 openssl req -newkey rsa:2048 -nodes -keyout slave-key.pem -out slave-req.pem \ -subj "/C=CN/ST=Beijing/L=Beijing/O=Example/CN=slave.example.com" openssl x509 -req -in slave-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem \ -set_serial 02 -out slave-cert.pem # 设置权限 chown mysql:mysql *.pem chmod 600 *-key.pem chmod 644 *-cert.pem ca-cert.pem# 主库SSL配置 [mysqld] ssl-ca = /etc/mysql/ssl/ca-cert.pem ssl-cert = /etc/mysql/ssl/master-cert.pem ssl-key = /etc/mysql/ssl/master-key.pem require_secure_transport = ON-- 从库配置SSL复制 CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.100', SOURCE_USER = 'repl_user', SOURCE_PASSWORD = 'StrongPassword@2024', SOURCE_AUTO_POSITION = 1, SOURCE_SSL = 1, SOURCE_SSL_CA = '/etc/mysql/ssl/ca-cert.pem', SOURCE_SSL_CERT = '/etc/mysql/ssl/slave-cert.pem', SOURCE_SSL_KEY = '/etc/mysql/ssl/slave-key.pem', SOURCE_SSL_VERIFY_SERVER_CERT = 1;3. 配置注意事项server-id必须唯一：整个复制拓扑中，每个MySQL实例的server-id必须不同GTID模式限制：不能使用CREATE TABLE ... SELECT语句不能在事务中混合使用事务表和非事务表不能使用CREATE TEMPORARY TABLE（事务内）binlog_format选择：ROW：记录每行数据变化，数据一致性最好，推荐使用STATEMENT：记录SQL语句，binlog体积小，但某些函数可能导致不一致MIXED：自动选择，不推荐4. 常见错误处理错误码错误描述原因分析解决方案1062Duplicate entry for key从库已存在相同主键数据使用pt-table-sync同步数据1032Can't find record从库缺少要更新/删除的数据检查数据一致性，使用pt-table-checksum校验1236Binary log position errorbinlog位置无效或已被清理重新初始化从库或使用GTID重建复制1045Access denied复制用户权限不足检查用户权限和密码1593Server_id not setserver-id未配置配置唯一的server-id1794Slave SQL thread retried复制冲突重试检查并发写入或网络问题13117GTID_PURGED can't be setGTID集合冲突使用RESET MASTER清理后重新配置八、故障排查和监控1. 关键监控指标指标名称说明告警阈值采集方法Seconds_Behind_Source复制延迟秒数>10s告警，>60s严重SHOW REPLICA STATUSReplica_IO_RunningI/O线程状态!=Yes告警SHOW REPLICA STATUSReplica_SQL_RunningSQL线程状态!=Yes告警SHOW REPLICA STATUSRpl_semi_sync_source_clients半同步从库数<1告警SHOW STATUSRpl_semi_sync_source_no_tx降级异步次数>0告警SHOW STATUSRelay_Log_Space中继日志大小>10GB告警SHOW REPLICA STATUS2. 常见问题诊断A. 复制延迟过大-- 查看复制延迟 SHOW REPLICA STATUS\G -- 分析延迟原因 -- 1. 检查从库负载 SHOW PROCESSLIST; SELECT * FROM performance_schema.threads WHERE TYPE = 'BACKGROUND' AND NAME LIKE '%replica%'; -- 2. 检查是否有大事务 SELECT * FROM performance_schema.events_transactions_current WHERE STATE = 'ACTIVE'\G -- 3. 检查并行复制效率 SELECT WORKER_ID, LAST_SEEN_TRANSACTION, APPLYING_TRANSACTION, LAST_APPLIED_TRANSACTION FROM performance_schema.replication_applier_status_by_worker; -- 4. 检查是否有锁等待 SELECT * FROM performance_schema.data_lock_waits;B. I/O线程停止-- 查看I/O线程状态 SHOW REPLICA STATUS\G -- 关注：Replica_IO_Running, Last_IO_Error, Last_IO_Errno -- 常见原因： -- 1. 网络连接问题 -- 2. 复制用户权限问题 -- 3. 主库binlog被清理 -- 4. 主库server-id变更 -- 重新连接测试 STOP REPLICA IO_THREAD; START REPLICA IO_THREAD;C. SQL线程停止-- 查看SQL线程状态 SHOW REPLICA STATUS\G -- 关注：Replica_SQL_Running, Last_SQL_Error, Last_SQL_Errno -- 查看最后执行的事务 SELECT * FROM performance_schema.replication_applier_status_by_coordinator\G SELECT * FROM performance_schema.replication_applier_status_by_worker WHERE LAST_ERROR_NUMBER != 0\G -- 数据不一致时的处理 -- 1. 使用pt-table-checksum校验 pt-table-checksum --user=root --password=xxx --host=192.168.1.100 \ --databases=mydb --tables=mytable -- 2. 使用pt-table-sync修复 pt-table-sync --print --user=root --password=xxx \ --sync-to-master h=192.168.1.101,D=mydb,t=mytable3. 备份与恢复A. 从库备份策略利用从库进行备份，不影响主库性能：#!/bin/bash # 文件：/opt/scripts/backup_from_slave.sh # 功能：从库热备份脚本 BACKUP_DIR="/backup/mysql" DATE=$(date +%Y%m%d_%H%M%S) MYSQL_USER="backup" MYSQL_PASS="BackupPass@2024" RETENTION_DAYS=7 # 创建备份目录 mkdir -p ${BACKUP_DIR}/${DATE} # 停止复制SQL线程，确保数据一致性 mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "STOP REPLICA SQL_THREAD;" # 记录复制位置 mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "SHOW REPLICA STATUS\G" > ${BACKUP_DIR}/${DATE}/replica_status.txt # 执行备份 xtrabackup --backup \ --user=${MYSQL_USER} \ --password=${MYSQL_PASS} \ --target-dir=${BACKUP_DIR}/${DATE}/data \ --slave-info \ --safe-slave-backup # 恢复复制 mysql -u${MYSQL_USER} -p${MYSQL_PASS} -e "START REPLICA SQL_THREAD;" # 压缩备份 cd ${BACKUP_DIR} tar -czf ${DATE}.tar.gz ${DATE} rm -rf ${DATE} # 清理过期备份 find ${BACKUP_DIR} -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete echo "Backup completed: ${BACKUP_DIR}/${DATE}.tar.gz"B. 使用备份重建从库# 解压备份 cd /backup/mysql tar -xzf 20240115_100000.tar.gz # 准备备份 xtrabackup --prepare --target-dir=/backup/mysql/20240115_100000/data # 停止MySQL systemctl stop mysqld # 清空数据目录 rm -rf /data/mysql/data/* # 恢复数据 xtrabackup --copy-back --target-dir=/backup/mysql/20240115_100000/data # 修改权限 chown -R mysql:mysql /data/mysql/data # 启动MySQL systemctl start mysqld # 配置复制（从xtrabackup_slave_info获取位置信息） cat /backup/mysql/20240115_100000/data/xtrabackup_slave_info # CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1 mysql -uroot -p << 'EOF' CHANGE REPLICATION SOURCE TO SOURCE_HOST = '192.168.1.100', SOURCE_USER = 'repl_user', SOURCE_PASSWORD = 'ReplPassword@2024', SOURCE_AUTO_POSITION = 1; START REPLICA; EOF九、总结1. 技术要点回顾GTID是现代MySQL复制的标配：简化故障切换，避免手动指定binlog位置半同步复制保障数据安全：rpl_semi_sync_source_wait_point=AFTER_SYNC配合超时设置，在性能和安全间取得平衡并行复制大幅降低延迟：WRITESET依赖追踪配合多个worker线程，将复制延迟从分钟级降到秒级Clone插件简化从库初始化：无需依赖外部工具，自动完成数据同步和复制配置监控告警是高可用基础：复制延迟、线程状态、半同步状态必须纳入监控体系2. 进阶学习方向MySQL Group Replication：多主架构，自动故障转移MySQL InnoDB Cluster：官方高可用解决方案MySQL Router：自动读写分离和故障切换Orchestrator：复制拓扑管理和自动化故障恢复ProxySQL：高性能MySQL代理3. 命令速查表命令说明SHOW MASTER STATUS查看主库binlog位置SHOW REPLICA STATUS\G查看从库复制状态START REPLICA启动复制STOP REPLICA停止复制RESET REPLICA ALL清除所有复制配置SHOW BINARY LOGS查看binlog文件列表PURGE BINARY LOGS TO 'file'清理指定文件之前的binlogSELECT @@GLOBAL.GTID_EXECUTED查看已执行的GTID集合SHOW PROCESSLIST查看当前连接和复制线程SHOW VARIABLES LIKE '%replica%'查看复制相关配置4. 术语表术语英文说明主库Master/Source提供写入的数据库节点从库Slave/Replica复制主库数据的数据库节点二进制日志Binary Log记录数据变更的日志文件中继日志Relay Log从库缓存主库binlog的日志文件GTIDGlobal Transaction ID全局事务标识符半同步复制Semi-sync Replication主库等待从库确认的复制模式异步复制Async Replication主库不等待从库确认的复制模式复制延迟Replication Lag从库数据落后主库的时间I/O线程I/O Thread从库接收binlog的线程SQL线程SQL Thread从库回放事务的线程参考资料MySQL主从复制搭建实战：数据同步零丢失配置指南
Rails 8 使用 SolidQueue 替代 Redis 架构分析一、背景与目标1. 项目背景 A. 业务场景 Rails 8 从默认技术栈中移除了 Redis。新的功能组件——SolidQueue（任务队列）、SolidCache（缓存）、SolidCable（实时消息传递）——完全运行在应用程序现有的关系数据库服务上。对于大多数 Rails 应用，可以不再依赖 Redis。 B. 痛点分析 Redis 虽然是快速、可靠的基础设施，但它增加了系统复杂性： - 需要单独部署、版本管理、补丁和监控服务器软件 - 需要配置持久化策略（RDB 快照、AOF 日志或两者） - 需要设置内存限制和淘汰策略 - 需要维护 Rails 与 Redis 之间的网络连接和防火墙规则 - 需要配置 Redis 客户端认证 - 需要构建和维护高可用 Redis 集群 - 需要协调 Sidekiq 进程的生命周期管理 2. 设计目标 A. 功能目标 - 使用关系数据库替代 Redis 实现任务队列功能 - 支持任务调度、并发控制、重试机制 - 提供监控和管理界面 B. 非功能目标 - 降低运维复杂性 - 减少基础设施组件数量 - 保持足够的性能水平 二、Redis 运维成本分析1. 直接成本 A. 服务器部署 - Redis 服务器软件安装与配置 - 版本升级与补丁管理 - 服务器资源监控 B. 持久化配置 - RDB 快照：内存快照持久化 - AOF 日志：追加文件日志 - 混合策略：结合两者优势 2. 间接成本 A. 网络与安全 - 防火墙规则配置 - Redis 客户端认证管理 - 高可用集群部署 B. 进程管理 - Sidekiq 进程编排 - 跨部署的生命周期管理 - 进程崩溃恢复 3. 调试复杂性 当任务出现问题时，需要同时调试 Redis 和 RDBMS 两个具有不同语义的数据存储，在不同的查询语言和工具之间切换上下文。还需要维护两套独立的备份策略。 三、SolidQueue 工作原理1. 核心技术：SKIP LOCKED PostgreSQL 9.5 增强了 SQL 的 `FOR UPDATE` 子句，添加了 `SKIP LOCKED` 选项。`FOR UPDATE` 创建排他行锁，`SKIP LOCKED` 进一步跳过当前被锁定的行。 这使得基于数据库的任务队列成为可能，即使在规模化场景下也能正常工作。 2. 任务获取流程 工作进程获取任务的查询： ```sql SELECT * FROM solid_queue_ready_executions WHERE queue_name = 'default' ORDER BY priority DESC, job_id ASC LIMIT 1 FOR UPDATE SKIP LOCKED ``` 自由的工作进程始终获取下一个可用任务。 这个数据库优化解决了早期数据库队列实现面临的根本问题：**锁竞争**。工作进程从不等待另一个进程，也从不阻塞。多个工作进程可以同时查询，PostgreSQL 保证每个进程获得唯一的任务。 3. 数据库表结构 SolidQueue 架构围绕三个核心表： ```mermaid graph TD subgraph SolidQueue 数据库表结构 A[solid_queue_jobs 任务元数据表] B[solid_queue_scheduled_executions 定时任务表] C[solid_queue_ready_executions 就绪任务表] end D[新任务] -->|已调度| B D -->|立即执行| C B -->|到达执行时间| C C -->|工作进程获取| E[执行中] E -->|完成| F[删除执行记录] E -->|失败| G[失败记录表] ``` A. solid_queue_jobs 存储所有任务元数据，包括任务名称、Ruby 类、开始和结束时间戳。默认情况下，每个排队请求都会记录在此表中，并在任务完成后永久保留。 B. solid_queue_scheduled_executions 定时任务等待直到其预定时间到达。 C. solid_queue_ready_executions 准备立即运行的任务排队在此，工作进程从中获取任务。 PostgreSQL 的 MVCC 设计通过内置的 autovacuum 进程很好地处理了任务表的快速和稳定 churn（大量插入和删除）。无需特殊调优。 4. 进程架构 ```mermaid graph LR subgraph SolidQueue 进程组件 A[Supervisor 监督进程] B[Workers 工作进程] C[Dispatchers 调度进程] D[Schedulers 定时任务进程] end A --> B A --> C A --> D B -->|轮询 0.1-0.2s| C D -->|每秒轮询| C C --> B ``` A. Workers（工作进程） 轮询 solid_queue_ready_executions，间隔可配置（高优先级队列最快可达 0.1 秒） B. Dispatchers（调度进程） 每秒轮询 solid_queue_scheduled_executions，将到期任务移至就绪表 C. Schedulers（定时任务进程） 按定义的时间表入队任务，管理周期性任务 D. Supervisor（监督进程） 监控所有进程，跟踪心跳并重启崩溃的进程 这些分离的关注点是 SolidQueue 最优雅的特性之一。每种进程类型在不同的表上操作，使用针对其工作负载优化的不同轮询间隔。 四、定时任务功能1. 配置方式 SolidQueue 内置了 cron 风格的周期性任务支持，无需额外库。编辑 config/recurring.yml： ```yaml # config/recurring.yml production: cleanup_old_sessions: class: CleanupSessionsJob schedule: every day at 2am queue: maintenance send_daily_digest: class: DailyDigestJob schedule: every day at 9am queue: mailers refresh_cache: class: CacheWarmupJob schedule: every hour queue: default ``` 2. 工作原理 ```mermaid sequenceDiagram participant S as Scheduler participant J as Job Queue participant W as Worker Note over S: 8:00 AM S->>J: 入队 refresh_cache 任务 W->>J: 获取并执行任务 S->>S: 调度下次运行（9:00 AM） Note over S: 9:00 AM S->>J: 入队 refresh_cache 任务 W->>J: 获取并执行任务 S->>S: 调度下次运行（10:00 AM） ``` A. 调度器运行时，找到到期的任务并入队执行 B. 同时，调度器还会为下一次出现的时间入队新任务 C. 这种模式具有崩溃恢复能力，因为调度是确定性的 五、并发控制功能1. 并发限制声明 SolidQueue 免费提供了 Sidekiq Enterprise 付费版才有的并发限制功能： ```ruby class ProcessUserOnboardingJob < ApplicationJob limits_concurrency to: 1, key: ->(user) { user.id }, duration: 15.minutes def perform(user) # 复杂的入职工作流 end end ``` `limits_concurrency to: 1` 确保在任何时候每个用户只运行一个 ProcessUserOnboardingJob 任务。 2. 信号量实现 ```mermaid graph TD A[新任务请求] --> B{检查信号量} B -->|未达到限制| C[获取信号量] B -->|已达到限制| D[加入阻塞队列] C --> E[执行任务] E --> F[释放信号量] F --> G[触发调度器] G --> D D --> H[解除阻塞，准备执行] ``` A. solid_queue_semaphores 跟踪并发限制 B. solid_queue_blocked_executions 保存等待信号量释放的任务 当任务完成时，它释放信号量并触发调度器解除下一个等待任务的阻塞。 六、监控与管理：Mission Control1. 功能对比 | 功能 | Sidekiq Pro/Enterprise | Mission Control Jobs | |-----|----------------------|---------------------| 价格 | $949-$1699/年 | 免费 | 实时任务状态 | 支持 | 支持 | 失败任务检查 | 支持 | 支持，带完整堆栈 | 批量操作 | 支持 | 支持 | 定时任务可视化 | 支持 | 支持 | SQL 查询 | 不支持 | 支持 | 2. 配置方式 ```ruby # config/routes.rb mount MissionControl::Jobs::Engine, at: "/jobs" ``` 3. SQL 集成优势 Mission Control 可以直接查询数据库： ```sql SELECT j.queue_name, COUNT(*) as failed_count FROM solid_queue_failed_executions fe JOIN solid_queue_jobs j ON j.id = fe.job_id WHERE fe.created_at > NOW() - INTERVAL '1 hour' GROUP BY j.queue_name; ``` SQL 是你已知的语言，在你已使用的工具中运行。无需外部解析，无需时间戳算术。 七、迁移路径：从 Sidekiq 到 SolidQueue1. 步骤概览 ```mermaid graph LR A[Sidekiq + Redis] --> B[更改队列适配器] B --> C[安装 SolidQueue] C --> D[转换定时任务配置] D --> E[更新 Procfile] E --> F[移除旧依赖] ``` 2. 详细步骤 A. 更改 Rails 队列适配器 ```ruby # config/environments/production.rb config.active_job.queue_adapter = :solid_queue ``` B. 安装 SolidQueue ```bash $ bundle add solid_queue $ rails solid_queue:install $ rails db:migrate ``` C. 转换定时任务配置 ```yaml # 旧配置：config/sidekiq.yml :schedule: cleanup_job: cron: '0 2 * * *' class: CleanupJob # 新配置：config/recurring.yml production: cleanup_job: class: CleanupJob schedule: every day at 2am ``` D. 更新 Procfile ```yaml web: bundle exec puma -C config/puma.rb jobs: bundle exec rake solid_queue:start ``` E. 移除旧依赖 ```ruby # Gemfile - DELETE # gem "redis" # gem "sidekiq" # gem "sidekiq-cron" ``` 八、性能与扩展性分析1. 性能基准 | 指标 | Redis + Sidekiq | SolidQueue | |-----|----------------|-----------| 任务吞吐量 | ~1000s 任务/秒 | ~200-300 任务/秒 | 任务延迟 | <1ms | ~100ms || 适用范围 | 99.9% 的应用 | 95% 的应用 |2. 扩展性评估公式 Nate Berkopec 的扩展性公式： **所需应用实例数 = 请求率（请求/秒）× 平均响应时间（秒）** 示例计算： - 应用每分钟处理 100 个请求 - 平均响应时间 200ms - 即约 1.67 请求/秒 - 所需实例：1.67 × 0.2 = 0.083 个实例 实际案例：37signals 每天处理 2000 万个任务，约每秒 230 个任务，全部运行在 PostgreSQL 上，无需 Redis。 3. 使用场景判断 **适合使用 SolidQueue**： - 任务处理少于 100 任务/秒 - 任务延迟容忍度大于 100ms - 希望简化基础设施 **需要保留 Redis**： - 持续处理数千任务/秒 - 任务延迟低于 1ms 至关重要 - 复杂的发布/订阅模式 - 需要密集的速率限制或计数器 九、实际部署指南1. 创建 Rails 8 应用 ```bash $ rails new myapp --database=postgresql $ cd myapp ``` Rails 8 自动配置 SolidQueue、SolidCache 和 SolidCable。 2. 配置队列数据库 ```yaml # config/database.yml development: primary: &primary_development <<: *default database: myapp_development queue: <<: *primary_development database: myapp_queue_development migrations_paths: db/queue_migrate ``` ```ruby # config/environments/development.rb config.active_job.queue_adapter = :solid_queue config.solid_queue.connects_to = { database: { writing: :queue } } ``` 3. 完整部署架构 ```mermaid graph TB subgraph 应用层 Web[Web 服务器 Puma] Jobs[SolidQueue 工作进程] end subgraph 数据层 PG[(PostgreSQL)] DB1[(主数据库)] DB2[(队列数据库)] end subgraph 管理层 MC[Mission Control /jobs] end Web --> DB1 Jobs --> DB2 MC --> DB2 DB1 -.共享存储.-> PG DB2 -.共享存储.-> PG ``` 十、技术选型对比1. Redis + Sidekiq vs SolidQueue | 方面 | Redis + Sidekiq | SolidQueue | |-----|----------------|-----------| | 设置复杂度 | 需要单独服务 + 配置 | 已内置 | | 查询语言 | Redis 命令 | SQL | | 监控 | 独立仪表板 | 与应用相同 | | 故障模式 | 6+ 种不同场景 | 2 种场景 | | 任务吞吐量 | ~1000s 任务/秒 | ~200-300 任务/秒 | | 适合应用比例 | 99.9% | 95% | | 成本 | 需付费企业版功能 | 全部免费 | 2. 运维复杂度对比 ```mermaid graph LR subgraph Redis + Sidekiq R1[Redis 服务器] R2[Sidekiq 进程] R3[持久化配置] R4[高可用集群] R1 --> R2 R1 --> R3 R1 --> R4 end subgraph SolidQueue S1[PostgreSQL] S2[SolidQueue 进程] S1 --> S2 end ``` 十一、常见问题与最佳实践1. 单数据库配置（备选方案） SolidQueue 推荐使用单独的数据库连接，但也可以运行在单一数据库中： 1. 将 db/queue_schema.rb 内容复制到常规迁移 2. 删除 db/queue_schema.rb 3. 从环境配置中移除 config.solid_queue.connects_to 4. 运行 rails db:migrate 2. 生产环境认证 不要忘记在生产环境中为 Mission Control 添加认证： ```ruby # config/initializers/mission_control.rb config.mission_control.jobs.base_controller_class = "AdminController" ``` 3. 轮询间隔 默认轮询间隔：定时任务 1 秒，就绪任务 0.2 秒。从 Sidekiq 迁移时，如果感觉任务"变慢"，需要调整期望。对于大多数应用，SolidQueue 的默认值工作良好。 十二、总结Redis 和 Sidekiq 是经过精心设计的工程产品，十多年来 Rails 应用从中受益匪浅。但对于大多数 Rails 应用，Redis 和 Sidekiq 解决的是你并不存在的问题，代价是你无法承受的复杂性。 SolidQueue 的核心优势： - 简化基础设施 - 减轻运维负担 - 保持足够性能 - 免费提供企业级功能 给 SolidQueue 一个尝试，让基础设施简化，运维负担减轻，专注于构建产品而不是维护技术栈。 参考资料I Love You, Redis, But I'm Leaving You for SolidQueue
（1）内存类型 MQ 节点将队列等运行状态数据不写硬盘，不影响业务数据持久化内存节点（RAM 节点）的特点运行时状态：内存节点仅将运行时状态（如交换器、队列、绑定、虚拟主机、用户和策略的定义）存储在内存中，不会将其写入磁盘。如果内存节点崩溃或重启，这些运行时状态会丢失，需要从磁盘节点或其他节点恢复。业务数据（消息）：消息的存储方式（是否持久化）由消息的 delivery-mode 属性决定，而不是节点类型。如果消息的 delivery-mode = 2（持久化），即使是在内存节点上，消息也会被写入磁盘。如果消息的 delivery-mode = 1（非持久化），消息仅存储在内存中，节点类型不会影响这一点。磁盘节点（Disk 节点）的特点运行时状态：磁盘节点将运行时状态存储在内存和磁盘中，确保即使节点重启，这些状态也不会丢失。业务数据（消息）：同样，消息的存储方式由 delivery-mode 属性决定，与节点类型无关。总结内存节点和磁盘节点的区别仅在于运行时状态的存储方式，不会直接影响业务数据（消息）的存储。消息的持久化由 delivery-mode 属性控制，无论是内存节点还是磁盘节点，持久化消息都会被写入磁盘。如果使用内存节点，需要注意运行时状态的丢失风险，尤其是在集群环境中，建议至少有一个磁盘节点来保存集群的运行时状态。（2）关于 DURABLE，只是影响队列是否存在，与其业务数据持久化无关是的，你的理解是正确的。在 RabbitMQ 中，durable 属性仅影响队列本身的定义是否在 RabbitMQ 服务器重启后仍然存在，而与队列内部的数据（消息）是否持久化无关。durable 属性的作用队列的持久化：当 durable=True 时，队列的定义会被持久化到磁盘。即使 RabbitMQ 服务器重启，队列仍然会存在。当 durable=False 时，队列的定义仅存储在内存中。如果 RabbitMQ 服务器重启，队列会被删除。与消息持久化的区别：durable 属性仅影响队列的定义，不涉及队列中消息的存储方式。消息是否持久化由消息的 delivery-mode 属性决定：delivery-mode=1：消息非持久化，仅存储在内存中。delivery-mode=2：消息持久化，会被写入磁盘。使用场景durable=True：适用于需要长期存在的队列，例如任务队列或消息队列，确保队列定义在 RabbitMQ 重启后仍然可用。即使队列是持久的，队列中的消息仍然需要单独设置为持久化（delivery-mode=2）才能确保消息不丢失。durable=False：适用于临时队列，例如 RPC 风格的应用程序，队列的生命周期与消费者绑定，消费者断开后队列可以自动删除。注意事项如果希望消息在 RabbitMQ 重启后仍然存在，必须同时满足以下两个条件：队列是持久的（durable=True）。消息是持久的（delivery-mode=2）。如果只设置了 durable=True 而没有设置 delivery-mode=2，队列定义会保留，但消息可能会丢失。总结durable 属性仅控制队列定义的持久化，与队列内部消息的存储方式无关。为了确保消息在 RabbitMQ 重启后不丢失，需要同时设置队列为持久化（durable=True）和消息为持久化（delivery-mode=2）。（3）关于如何不落盘业务数据，需要消息中指定 delivery-mode 为 2delivery-mode 是 AMQP 协议中定义的一个消息属性，用于指示 RabbitMQ 如何处理消息的存储和持久化。它有两个可能的值：delivery-mode = 1：这是默认值，表示消息是非持久化的。RabbitMQ 会将消息保留在内存中，不会将其写入磁盘。如果 RabbitMQ 重启，这些非持久化的消息将会丢失。delivery-mode = 2：表示消息是持久化的。RabbitMQ 会将消息写入磁盘，确保即使 RabbitMQ 重启，消息仍然会保留在队列中。这种模式提供了更高的可靠性，但可能会影响性能，因为磁盘 I/O 比内存 I/O 慢。使用场景delivery-mode = 1：适用于对消息丢失不敏感的场景，例如实时日志或临时数据，可以最大限度地减少延迟。delivery-mode = 2：适用于需要确保消息不丢失的场景，例如金融交易或关键业务数据。性能影响使用 delivery-mode = 2 时，由于需要将消息写入磁盘，可能会增加发布消息的延迟，尤其是在高并发或 I/O 负载较高的情况下。如果需要更高的性能，可以结合其他优化技术，例如事务或批量确认。总结delivery-mode 是一个重要的消息属性，开发者需要根据业务需求选择合适的模式，以在消息的可靠性和性能之间找到平衡。（4）影响 mq 性能的很大原因是 HA 模式加上数据持久化是的，HA 模式（高可用模式）和数据持久化是影响 RabbitMQ 性能的两个重要因素。它们虽然提供了更高的可靠性和容错能力，但也会带来额外的开销，从而影响系统的整体性能。HA 模式对性能的影响HA 模式通过将队列镜像到多个节点来实现高可用性，但这会引入以下性能开销：节点间协调：每次发布或消费消息时，RabbitMQ 需要在所有镜像节点之间进行协调，以确保数据一致性。镜像节点越多，协调的开销越大，延迟也会增加。网络开销：镜像节点之间的数据同步需要通过网络传输，可能会增加网络带宽的消耗。资源消耗：每个镜像节点都需要存储队列的完整副本，这会增加内存和磁盘的使用量。数据持久化对性能的影响数据持久化通过将消息写入磁盘来确保消息在 RabbitMQ 重启后不会丢失，但这也会带来以下性能问题：磁盘 I/O 开销：每次持久化消息时，RabbitMQ 都需要将消息写入磁盘，而磁盘 I/O 的速度远低于内存操作。在高并发场景下，频繁的磁盘写入可能成为性能瓶颈。延迟增加：持久化操作会增加消息发布的延迟，尤其是在磁盘 I/O 负载较高的情况下。HA 模式 + 数据持久化的综合影响当 HA 模式和持久化同时启用时，性能影响会进一步加剧：双重写入开销：消息不仅需要写入本地磁盘，还需要同步到所有镜像节点。双重协调开销：持久化操作和镜像节点之间的同步都需要额外的协调，这会增加系统的复杂性。资源消耗倍增：每个镜像节点都需要存储持久化消息的副本，这会显著增加内存和磁盘的使用量。优化建议为了在可靠性和性能之间找到平衡，可以考虑以下优化措施：合理配置 HA 模式：根据业务需求，选择适当的镜像节点数量。通常，2-3 个镜像节点足以满足大多数场景的高可用性需求。选择性持久化：仅对关键消息启用持久化（delivery-mode=2），对非关键消息使用非持久化（delivery-mode=1）。优化磁盘性能：使用高性能的 SSD 磁盘，以减少持久化操作的延迟。集群设计：将生产者和消费者直接连接到其队列所在的节点，减少网络传输的开销。监控和调优：定期监控 RabbitMQ 的性能指标（如消息速率、延迟、资源使用率），并根据实际情况进行调整。总结HA 模式和持久化是 RabbitMQ 提供高可靠性的重要特性，但它们会显著影响性能。在实际应用中，需要根据业务需求权衡可靠性和性能，并通过合理的配置和优化来最大限度地减少性能损失。（5）设置 delivery-mode 为 2 有几种模式在 RabbitMQ 中，设置 delivery-mode 为 2（即持久化消息）可以通过以下几种方式实现：在消息发布时设置在发布消息时，通过设置消息的 BasicProperties 来指定 delivery-mode 为 2。以下是不同编程语言中的实现示例：Java（使用 RabbitMQ Java 客户端）AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder() .deliveryMode(2) // 设置为持久化 .build(); channel.basicPublish(exchange, routingKey, properties, message.getBytes());Python（使用 Pika 库）properties = pika.BasicProperties(delivery_mode=2) # 设置为持久化 channel.basic_publish(exchange='exchange_name', routing_key='routing_key', body='message_body', properties=properties)Node.js（使用 amqplib 库）const properties = { deliveryMode: 2 }; // 设置为持久化 channel.publish('exchange_name', 'routing_key', Buffer.from('message_body'), properties);在队列声明时设置虽然 delivery-mode 是消息级别的属性，但可以通过声明持久化队列（durable=True）来确保队列本身在 RabbitMQ 重启后仍然存在。持久化队列与持久化消息通常结合使用，以实现完整的消息可靠性。Javaboolean durable = true; // 设置为持久化队列 channel.queueDeclare("queue_name", durable, false, false, null);Pythonchannel.queue_declare(queue='queue_name', durable=True) # 设置为持久化队列Node.jschannel.assertQueue('queue_name', { durable: true }); // 设置为持久化队列通过策略（Policy）设置RabbitMQ 支持通过策略（Policy）为队列或交换器设置默认的 delivery-mode。这种方式可以全局控制消息的持久化行为。设置策略rabbitmqctl set_policy my_policy "^my_queue$" '{"delivery-mode":2}' --apply-to queues解释my_policy：策略名称。^my_queue$：匹配的队列名称（支持正则表达式）。{"delivery-mode":2}：将匹配队列的消息默认设置为持久化。--apply-to queues：策略应用于队列。通过管理界面设置RabbitMQ 的管理界面（Management Plugin）也支持通过策略设置 delivery-mode。步骤打开 RabbitMQ 管理界面（通常是 http://localhost:15672）。导航到 Policies 选项卡。点击 Add a new policy。在 Pattern 中输入队列名称（支持正则表达式）。在 Definition 中添加 delivery-mode 为 2。点击 Add policy 保存。总结设置 delivery-mode 为 2 的主要方式包括：在消息发布时设置：通过 BasicProperties 指定。在队列声明时设置：通过 durable=True 声明持久化队列。通过策略设置：使用 RabbitMQ 的策略功能全局控制。通过管理界面设置：在 RabbitMQ 管理界面中配置策略。根据具体需求选择合适的方式，通常建议在消息发布时显式设置 delivery-mode，以确保消息的持久化行为符合预期。
安装datagrip，可以使用链接http://vip.123pan.cn/1815238395/download/datagrip/2024.1.5/datagrip-2024.1.5.exe使用链接https://ipfs.io/ipfs/bafybeih65no5dklpqfe346wyeiak6wzemv5d7z2ya7nssdgwdz4xrmdu6i/下载jetbra.zip文件。或者直接从这里http://vip.123pan.cn/1815238395/download/datagrip/%E6%BF%80%E6%B4%BB/jetbra-8f6785eac5e6e7e8b20e6174dd28bb19d8da7550.zip解压到datagrip的bin目录下。进入bin/jetbra/，查看readme.txtOperation guide: 1. add -javaagent:/path/to/ja-netfilter.jar=jetbrains to your vmoptions (manual or auto) 2. log out of the jb account in the 'Licenses' window 3. use key on page https://jetbra.in/5d84466e31722979266057664941a71893322460 4. plugin 'mymap' has been deprecated since version 2022.1 5. don't care about the activation time, it is a fallback license and will not expire Enjoy it~ JBR17: add these 2 lines to your vmoptions file: (for manual, without any whitespace chars) --add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED NEW: Auto configure vmoptions: macOS or Linux: execute "scripts/install.sh" Windows: double click to execute "scripts\install-current-user.vbs" (For current user) "scripts\install-all-users.vbs" (For all users) 找到安装datagrip目录的datagrip64.vmoptions，根据上述readme.txt内容加入进去。然后启动datagrip，不要使用账号密码登录，选择激活码54H0PAD972IO7OS-[binary]-[binary]-[binary]
研发发来了一个报错，这个报错是sql_mode=only_full_group_by兼容性导致。直接修改sql_mode就可以了。com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: In aggregated query without GROUP BY, expression #2 of SELECT list contains nonaggregated column 'xxx.bm.gid'; this is incompatible with sql_mode=only_full_group_by at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_152] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_152] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_152] at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_152]临时修改## 查看 -- 开启-- 查看数据库版本和 Session级信息 SELECT VERSION(),@@sql_mode; -- 查看数据库版本和 GLOBAL级信息 SELECT VERSION(),@@GLOBAL.sql_mode; ## 关闭 -- 关闭 session级 SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); -- 关闭 GLOBAL级 SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); 查看线上配置修改配置文件 mysql: image: harbor.op123.ren:44301/library/mysql:5.7.35 command: --sql-mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" restart: "no" container_name: mysql environment: - MYSQL_ROOT_PASSWORD=xxx - TZ=Asia/Shanghai - SET_CONTAINER_TIMEZONE=true - CONTAINER_TIMEZONE=Asia/Shanghai # 添加性能相关的环境变量 - MYSQL_INNODB_BUFFER_POOL_SIZE=4G - MYSQL_INNODB_LOG_FILE_SIZE=256M - MYSQL_INNODB_LOG_BUFFER_SIZE=64M - MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT=2 - MYSQL_INNODB_FLUSH_METHOD=O_DIRECT - MYSQL_MAX_CONNECTIONS=1000 # 添加日志相关的环境变量 - MYSQL_LOG_CONSOLE=true - MYSQL_LOG_ERROR=/var/log/mysql/custom-error.log - MYSQL_LOG_QUERIES_ENABLED=true - MYSQL_LOG_QUERIES_FILE=/var/log/mysql/queries.log networks: yewu-network: ipv4_address: 192.168.177.55 cap_add: - SYS_NICE # CAP_SYS_NICE ports: - 3306:3306 volumes: - ./data/mysql/conf:/etc/mysql/conf.d - ./data/mysql/data:/var/lib/mysql - ./data/mysql/logs:/var/log/mysql - /etc/localtime:/etc/localtime:ro # 添加资源限制 deploy: resources: limits: cpus: '4' memory: 8G reservations: cpus: '4' memory: 8G