在现代应用开发中,单一数据库很难满足所有业务场景 —— 关系型数据库的事务可靠性、文档数据库的灵活扩展、内存数据库的极速响应,恰好是互补的优势。本文将以 Docker Compose 为基础,带你搭建 Redis+MongoDB+MySQL 协同架构,详解三者的定位分工、数据流转逻辑,以及 2025 年最新实战场景,让你彻底搞懂 “三库联动” 的核心玩法。

一、先明确核心定位:为什么要一起用?

三者的协同核心是 “各司其职、优势互补”,避免 “用一个数据库解决所有问题” 的尴尬。先理清各自的角色定位,才能设计合理的架构:

数据库类型核心优势2025 年关键特性适用场景
MySQL关系型数据库强事务(ACID)、结构化存储、复杂查询(JOIN / 索引)、数据一致性8.4 版本原生支持 JSON 字段优化、异步复制性能提升 30%用户核心数据(账号、订单、支付)、需事务保障的业务(下单扣库存)、结构化报表
MongoDB文档型 NoSQL非结构化 / 半结构化存储、灵活 Schema、水平扩展、高写入吞吐量7.0 版本向量搜索优化、时序数据存储增强用户行为日志、商品详情(多变字段)、内容管理(文章 / 评论)、物联网设备数据
Redis内存数据库毫秒级响应、支持多种数据结构(Hash/Set/ZSet)、缓存 / 限流 / 分布式锁7.4 版本持久化性能优化、AI 模型缓存支持热点数据缓存(减轻 MySQL 压力)、会话存储(登录态)、实时计数(点赞 / 访问量)、秒杀限流

核心协同逻辑:MySQL 存 “核心结构化数据”(保证可靠性)→ Redis 缓存 “热点数据”(提升响应速度)→ MongoDB 存 “非结构化 / 高写入数据”(保证灵活性),三者通过应用层联动,兼顾性能、可靠性和扩展性。

二、实战:Docker Compose 一键部署三库

基于之前的 Docker 基础,我们用 docker-compose.yml 快速搭建可协同的三库环境,无需手动配置网络(自动创建自定义网络,三库互通)。

2.1 编写 docker-compose.yml(2025 优化版)

yaml

version: "3.9"

# 自定义网络:三库在同一网络,可通过服务名直接访问
networks:
  app-network:
    driver: bridge

# 数据卷:持久化三库数据(容器删除后数据不丢失)
volumes:
  mysql-data:  # MySQL数据卷
  mongo-data:  # MongoDB数据卷
  redis-data:  # Redis数据卷

services:
  # 1. MySQL 8.4(关系型核心存储)
  mysql:
    image: mysql:8.4  # 2025最新稳定版
    container_name: app-mysql
    networks:
      - app-network
    volumes:
      - mysql-data:/var/lib/mysql  # 数据持久化
      - ./init-mysql.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化脚本(可选)
    environment:
      MYSQL_ROOT_PASSWORD: Root@123456  # 根密码
      MYSQL_DATABASE: app_db  # 自动创建数据库
      MYSQL_USER: app_user  # 应用专用用户
      MYSQL_PASSWORD: App@123456  # 应用用户密码
    ports:
      - "3306:3306"
    restart: always
    # 安全配置(生产环境必备)
    command: --default-authentication-plugin=mysql_native_password
    healthcheck:  # 健康检查(确保启动完成)
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uapp_user", "-pApp@123456"]
      interval: 10s
      timeout: 5s
      retries: 3

  # 2. MongoDB 7.0(文档型存储)
  mongodb:
    image: mongo:7.0  # 2025最新稳定版
    container_name: app-mongo
    networks:
      - app-network
    volumes:
      - mongo-data:/data/db  # 数据持久化
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: Root@123456
    ports:
      - "27017:27017"
    restart: always
    # 安全配置:启用认证(默认不启用,生产必开)
    command: --auth
    healthcheck:
      test: ["CMD", "mongosh", "admin", "-uroot", "-pRoot@123456", "--eval", "db.runCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 3

  # 3. Redis 7.4(内存缓存/计数)
  redis:
    image: redis:7.4-alpine  # 轻量版,2025最新
    container_name: app-redis
    networks:
      - app-network
    volumes:
      - redis-data:/data  # 持久化(AOF+RDB混合模式)
      - ./redis.conf:/etc/redis/redis.conf  # 自定义配置(可选)
    environment:
      REDIS_PASSWORD: Root@123456  # 密码认证(生产必开)
    ports:
      - "6379:6379"
    restart: always
    command: redis-server /etc/redis/redis.conf --requirepass Root@123456
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "Root@123456", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

2.2 可选:Redis 配置文件(redis.conf)

为优化 Redis 性能和持久化,创建 redis.conf 文件(与 docker-compose.yml 同级):

conf

# 持久化配置(2025推荐混合模式)
appendonly yes  # 启用AOF(每修改同步,保证数据不丢失)
appendfsync everysec  # 每秒同步一次(性能+可靠性平衡)
save 900 1  # 900秒内1次修改则RDB快照
save 300 10 # 300秒内10次修改则RDB快照

# 内存优化
maxmemory 1gb  # 限制最大内存(根据服务器配置调整)
maxmemory-policy allkeys-lru  # 内存满时淘汰最少使用的key

# 网络安全
bind 0.0.0.0  # 允许所有IP访问(Docker环境安全)
protected-mode yes  # 保护模式(需密码才能访问)

2.3 启动与验证

bash

运行

# 启动所有服务(后台运行)
docker compose up -d

# 查看启动状态(确保所有服务都是healthy)
docker compose ps

# 验证各服务可用性
# 1. 验证MySQL
docker exec -it app-mysql mysql -uapp_user -pApp@123456 -e "SELECT VERSION();"

# 2. 验证MongoDB
docker exec -it app-mongo mongosh admin -uroot -pRoot@123456 --eval "db.version();"

# 3. 验证Redis
docker exec -it app-redis redis-cli -a Root@123456 ping  # 输出PONG则成功

关键优势

  • 三库在同一 Docker 网络,应用可通过 mysqlmongodbredis 服务名直接连接(无需记 IP);
  • 数据卷持久化,容器重启 / 删除后数据不丢失;
  • 健康检查确保服务就绪后再供应用访问,避免启动顺序问题。

三、核心协同场景:三库怎么配合工作?

以 “电商应用” 为例,详解三个数据库的联动逻辑,结合代码片段(Python 示例)让你直观理解。

场景 1:用户登录与信息查询

需求:用户登录后,会话保持 1 小时,后续查询用户信息优先走缓存,避免频繁查 MySQL。

数据库角色具体操作
MySQL存储用户核心信息(id、用户名、密码哈希、手机号、注册时间)
Redis存储登录会话(Session:key=user:session:{token},value = 用户 ID,过期 1 小时)、热点用户缓存(key=user:info:{id},value = 用户信息 JSON)
MongoDB存储用户行为日志(登录时间、登录设备、浏览记录)

代码示例(Python)

python

运行

import redis
import pymysql
from pymongo import MongoClient
import uuid
import time

# 1. 连接三库(Docker环境:服务名作为主机)
redis_client = redis.Redis(
    host="redis", port=6379, password="Root@123456", decode_responses=True
)
mysql_conn = pymysql.connect(
    host="mysql", user="app_user", password="App@123456", db="app_db", charset="utf8"
)
mongo_client = MongoClient(
    "mongodb://root:Root@123456@mongodb:27017/?authSource=admin"
)
mongo_db = mongo_client["app_log"]  # MongoDB数据库名
user_log_coll = mongo_db["user_login_log"]  # 登录日志集合

# 2. 用户登录逻辑
def user_login(username, password):
    # 步骤1:查MySQL验证账号密码(核心数据存在MySQL)
    with mysql_conn.cursor() as cursor:
        sql = "SELECT id, username, phone FROM users WHERE username=%s AND password=%s"
        cursor.execute(sql, (username, password))  # 实际项目中密码需哈希(如bcrypt)
        user = cursor.fetchone()
        if not user:
            return {"code": 401, "msg": "账号密码错误"}
    
    user_id, username, phone = user
    # 步骤2:生成Session存入Redis(会话缓存)
    token = str(uuid.uuid4())
    redis_client.setex(f"user:session:{token}", 3600, user_id)  # 1小时过期
    
    # 步骤3:用户信息存入Redis缓存(热点数据加速)
    redis_client.hset(
        f"user:info:{user_id}",
        mapping={"username": username, "phone": phone, "update_time": int(time.time())}
    )
    redis_client.expire(f"user:info:{user_id}", 86400)  # 缓存24小时
    
    # 步骤4:登录日志存入MongoDB(非结构化数据)
    user_log_coll.insert_one({
        "user_id": user_id,
        "username": username,
        "login_time": time.strftime("%Y-%m-%d %H:%M:%S"),
        "ip": "192.168.1.100",
        "device": "Chrome/120.0"
    })
    
    return {"code": 200, "data": {"token": token, "user_id": user_id}}

# 3. 查询用户信息(优先查Redis缓存)
def get_user_info(token):
    # 步骤1:验证Session(Redis快速查询)
    user_id = redis_client.get(f"user:session:{token}")
    if not user_id:
        return {"code": 403, "msg": "登录已过期"}
    
    # 步骤2:查Redis缓存(热点数据)
    user_cache = redis_client.hgetall(f"user:info:{user_id}")
    if user_cache:
        return {"code": 200, "data": user_cache}
    
    # 步骤3:缓存未命中,查MySQL并更新缓存
    with mysql_conn.cursor() as cursor:
        sql = "SELECT username, phone FROM users WHERE id=%s"
        cursor.execute(sql, (user_id,))
        user = cursor.fetchone()
        if not user:
            return {"code": 404, "msg": "用户不存在"}
    
    # 更新缓存
    redis_client.hset(f"user:info:{user_id}", mapping={"username": user[0], "phone": user[1]})
    redis_client.expire(f"user:info:{user_id}", 86400)
    
    return {"code": 200, "data": {"username": user[0], "phone": user[1]}}

场景 2:商品详情与库存管理

需求:商品详情字段多变(如规格、图片、描述),热点商品需快速响应,下单时需保证库存一致性。

数据库角色具体操作
MySQL存储商品核心数据(id、名称、价格、库存、分类 ID)、订单数据(需事务)
Redis缓存热点商品详情(减轻 MongoDB 压力)、秒杀库存计数(原子操作保证并发安全)
MongoDB存储商品详情(富文本描述、多规格、图片列表、售后政策)

核心逻辑

  1. 商品上架时:MySQL 存入核心信息,MongoDB 存入详情,Redis 缓存热点商品(如销量前 100 的商品);
  2. 用户浏览时:优先查 Redis → 未命中查 MongoDB → 同时更新 Redis 缓存;
  3. 下单时:MySQL 用事务扣减库存(保证一致性),Redis 同步更新库存缓存(避免缓存脏数据)。

关键代码片段(下单逻辑)

python

运行

def create_order(user_id, product_id, quantity):
    # 步骤1:Redis预扣库存(防止超卖,原子操作)
    stock_key = f"product:stock:{product_id}"
    remaining_stock = redis_client.decrby(stock_key, quantity)
    if remaining_stock < 0:
        # 库存不足,回滚Redis
        redis_client.incrby(stock_key, quantity)
        return {"code": 400, "msg": "库存不足"}
    
    try:
        # 步骤2:MySQL事务扣减库存+创建订单(保证一致性)
        with mysql_conn.cursor() as cursor:
            mysql_conn.begin()  # 开启事务
            
            # 1. 检查并扣减库存
            sql = "SELECT stock FROM products WHERE id=%s FOR UPDATE"  # 行锁防止并发
            cursor.execute(sql, (product_id,))
            product = cursor.fetchone()
            if not product or product[0] < quantity:
                mysql_conn.rollback()
                redis_client.incrby(stock_key, quantity)  # 回滚Redis
                return {"code": 400, "msg": "库存不足"}
            
            # 2. 扣减库存
            update_sql = "UPDATE products SET stock=stock-%s WHERE id=%s"
            cursor.execute(update_sql, (quantity, product_id))
            
            # 3. 创建订单
            order_sql = "INSERT INTO orders (user_id, product_id, quantity, status) VALUES (%s, %s, %s, 'pending')"
            cursor.execute(order_sql, (user_id, product_id, quantity))
            order_id = cursor.lastrowid
            
            mysql_conn.commit()  # 提交事务
        
        # 步骤3:MongoDB存入订单详情(非结构化数据)
        mongo_db["order_details"].insert_one({
            "order_id": order_id,
            "user_id": user_id,
            "product_id": product_id,
            "quantity": quantity,
            "create_time": time.strftime("%Y-%m-%d %H:%M:%S"),
            "payment_info": {},  # 后续支付信息补充
            "logistics_info": {}  # 后续物流信息补充
        })
        
        return {"code": 200, "data": {"order_id": order_id}}
    
    except Exception as e:
        mysql_conn.rollback()
        redis_client.incrby(stock_key, quantity)  # 回滚Redis
        return {"code": 500, "msg": f"下单失败:{str(e)}"}

场景 3:实时统计与行为分析

需求:统计商品实时访问量、用户点赞数,同时收集用户行为数据用于后续分析。

数据库角色具体操作
Redis实时计数(ZSet 排序、Hash 计数),如商品访问量、点赞数
MongoDB存储用户行为明细(点击、浏览、收藏),支持后续聚合分析
MySQL存储统计结果汇总(如每日访问量、总点赞数),用于报表

核心逻辑

  • 用户点击商品:Redis incr 原子递增访问量,MongoDB 存入点击明细;
  • 每日凌晨:定时任务从 Redis 读取统计数据,汇总后写入 MySQL(供报表查询)。

四、2025 年关键优化:性能与可靠性

4.1 数据一致性保障

三库协同的核心痛点是 数据一致性,2025 年推荐以下方案:

  1. 缓存更新策略:Cache-Aside 模式

    • 读:先查 Redis → 未命中查源数据库(MySQL/MongoDB)→ 更新 Redis;
    • 写:先更源数据库 → 再删 Redis 缓存(而非直接更新,避免并发脏数据)。
  2. Redis 缓存穿透 / 击穿 / 雪崩防护

    • 穿透:不存在的 key 缓存空值(过期 1 分钟),或用布隆过滤器;
    • 击穿:热点 key 设置永不过期,或用互斥锁;
    • 雪崩:缓存过期时间加随机值(如 24 小时 ±30 分钟),避免同时过期。
  3. MySQL 与 MongoDB 数据同步

    • 关键数据:应用层双写(如订单数据同时写入 MySQL 和 MongoDB 备份);
    • 非关键数据:使用 MySQL 触发器 + 消息队列(如 RabbitMQ)异步同步到 MongoDB。

4.2 性能优化技巧

  1. Redis 优化

    • 启用 lazyfree(惰性删除),避免大 key 删除阻塞线程;
    • 热点数据用 Hash 存储(减少内存占用),而非多个 String;
    • 2025 新特性:Redis 7.4 支持 MEMORY USAGE 精确计算 key 内存,便于优化。
  2. MongoDB 优化

    • 为查询字段创建索引(如 user_idorder_id);
    • 大文档拆分(如商品详情和评论分开存储);
    • 2025 新特性:MongoDB 7.0 向量搜索支持,可直接存储 AI 嵌入向量,配合 Redis 缓存热门向量查询结果。
  3. MySQL 优化

    • 核心表(users、orders)分库分表(如按用户 ID 哈希分表);
    • 读写分离(主库写,从库读),2025 年 MySQL 8.4 异步复制延迟降低至毫秒级;
    • 避免大事务,拆分长事务为短事务。

4.3 安全最佳实践

  1. 容器安全

    • 所有数据库容器非 root 运行(在 docker-compose.yml 中添加 user: "1001:1001");
    • 限制容器资源(如 MySQL 内存限制 2GB,Redis 内存限制 1GB),避免耗尽主机资源。
  2. 数据库安全

    • 禁用 root 用户远程访问,创建应用专用用户(如 MySQL 的 app_user),仅授予必要权限;
    • 密码定期更换,敏感数据加密存储(如 MySQL 用 AES_ENCRYPT 加密手机号);
    • 开启数据库审计日志(MySQL 启用 general_log,MongoDB 启用 auditLog)。

五、什么时候不适合三库协同?

三库协同虽强,但并非万能,以下场景可简化架构:

  1. 小型应用 / 初创项目:用户量少、数据结构简单,用 MySQL + Redis 即可(MongoDB 可省略);
  2. 纯静态内容服务:仅需缓存和简单存储,用 Redis + 对象存储(如 S3)即可;
  3. 高并发写入但无需事务:用 MongoDB + Redis (MySQL 可省略,如日志收集系统)。

六、总结与下一步

Redis+MongoDB+MySQL 的协同架构,本质是 “用对工具做对事”:MySQL 保可靠性,Redis 提性能,MongoDB 扩灵活性。通过 Docker Compose 可快速搭建环境,2025 年的数据库新特性(如 MySQL 异步复制优化、MongoDB 向量搜索、Redis 持久化增强)让三者协同更高效。

下一步学习建议

  1. 集成消息队列(如 RabbitMQ/Kafka):解决三库异步同步问题(如 MySQL 数据变更异步同步到 MongoDB);
  2. 监控告警:用 Prometheus + Grafana 监控三库性能(如 Redis 缓存命中率、MySQL 慢查询、MongoDB 索引使用率);
  3. 云原生部署:将 Docker 架构迁移到 Kubernetes,实现自动扩缩容、滚动更新(适合中大型项目)。

如果你的业务涉及高并发、复杂数据结构、实时响应等需求,三库协同架构将是 2025 年的最优解之一。动手尝试本文的 Docker Compose 配置,结合实际项目场景调整,就能快速落地!

更多推荐