Ver Fonte

添加 srv 的 ha 集群部署

reghao há 3 semanas atrás
pai
commit
e7a651ff71
42 ficheiros alterados com 1535 adições e 0 exclusões
  1. 56 0
      ha/mysql80/conf/my1.cnf
  2. 56 0
      ha/mysql80/conf/my2.cnf
  3. 56 0
      ha/mysql80/conf/my3.cnf
  4. 13 0
      ha/mysql80/conf/mysqlrouter.conf
  5. 74 0
      ha/mysql80/create_user.sh
  6. 98 0
      ha/mysql80/docker-compose.yml
  7. 67 0
      ha/mysql80/docker-compose1.yml
  8. 36 0
      ha/mysql80/docker-compose2.yml
  9. 36 0
      ha/mysql80/docker-compose3.yml
  10. 43 0
      ha/mysql80/init_mgr.sh
  11. 24 0
      ha/mysql80/init_mysql80-1.sh
  12. 24 0
      ha/mysql80/init_mysql80-2.sh
  13. 24 0
      ha/mysql80/init_mysql80-3.sh
  14. 47 0
      ha/mysql80/init_mysql80.sh
  15. 84 0
      ha/mysql80/init_proxysql.sh
  16. 14 0
      ha/mysql80/join_cluster.sh
  17. 31 0
      ha/mysql80/mgr_bootstrap.sh
  18. 40 0
      ha/rabbitmq/docker-compose-1.yml
  19. 38 0
      ha/rabbitmq/docker-compose-2.yml
  20. 38 0
      ha/rabbitmq/docker-compose-3.yml
  21. 13 0
      ha/rabbitmq/init_rabbitmq1.sh
  22. 13 0
      ha/rabbitmq/init_rabbitmq2.sh
  23. 13 0
      ha/rabbitmq/init_rabbitmq3.sh
  24. 8 0
      ha/rabbitmq/join_cluster.sh
  25. 106 0
      ha/redis/docker-compose.yml
  26. 63 0
      ha/redis/docker-compose1.yml
  27. 63 0
      ha/redis/docker-compose2.yml
  28. 62 0
      ha/redis/docker-compose3.yml
  29. 17 0
      ha/redis/init_redis1.sh
  30. 17 0
      ha/redis/init_redis2.sh
  31. 17 0
      ha/redis/init_redis3.sh
  32. 9 0
      ha/redis/redis/redis.conf
  33. 8 0
      ha/redis/sentinel/sentinel1.conf
  34. 8 0
      ha/redis/sentinel/sentinel2.conf
  35. 8 0
      ha/redis/sentinel/sentinel3.conf
  36. 30 0
      ha/zookeeper/docker-compose-1.yml
  37. 30 0
      ha/zookeeper/docker-compose-2.yml
  38. 30 0
      ha/zookeeper/docker-compose-3.yml
  39. 79 0
      ha/zookeeper/docker-compose.yml
  40. 14 0
      ha/zookeeper/init_zk1.sh
  41. 14 0
      ha/zookeeper/init_zk2.sh
  42. 14 0
      ha/zookeeper/init_zk3.sh

+ 56 - 0
ha/mysql80/conf/my1.cnf

@@ -0,0 +1,56 @@
+[mysqld]
+# --- 1. 基础网络与端口配置 ---
+user            = mysql
+port            = 3306
+bind-address    = 0.0.0.0
+mysqlx-port     = 33060
+mysqlx-bind-address = 0.0.0.0
+
+# --- 2. 目录路径配置 ---
+# 注意:容器内路径。确保 Docker volumes 挂载了这些位置
+datadir         = /var/lib/mysql
+log-error       = /var/log/mysql/error.log
+secure-file-priv= /var/lib/mysql-files
+
+# --- 3. 基础性能与存储引擎 ---
+default_storage_engine = InnoDB
+disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,EXAMPLE"
+
+# --- 4. 事务与复制核心配置 (MGR 强制要求) ---
+server_id               = 1
+gtid_mode               = ON
+enforce_gtid_consistency = ON
+binlog_format           = ROW
+log_slave_updates       = ON
+binlog_checksum         = NONE
+master_info_repository  = TABLE
+relay_log_info_repository = TABLE
+transaction_write_set_extraction = XXHASH64
+
+# --- 5. MGR (Group Replication) 专项配置 ---
+plugin_load_add         = 'group_replication.so'
+# 使用 loose- 前缀避免启动时的未知变量错误
+# 集群唯一标识 (必须是标准 UUID)
+loose-group_replication_group_name="235e4553-3508-46c2-b3a3-768fc0c829e2"
+# 节点间同步数据的通信地址(建议使用容器固定 IP)
+loose-group_replication_local_address = "192.168.0.211:33061"
+# 集群种子节点地址列表
+loose-group_replication_group_seeds   = "192.168.0.211:33061,192.168.0.212:33061,192.168.0.213:33061"
+# 启动行为
+loose-group_replication_start_on_boot = OFF
+loose-group_replication_bootstrap_group = OFF
+# 模式配置 (推荐单主模式)
+loose-group_replication_single_primary_mode = ON
+loose-group_replication_enforce_update_everywhere_checks = OFF
+
+# --- 6. 日志与超时优化 ---
+slow_query_log      = 1
+slow_query_log_file = /var/log/mysql/slow.log
+long_query_time     = 2
+interactive_timeout = 28800
+wait_timeout        = 28800
+
+# 限制 binlog 的总大小或保留天数(MySQL 8.0 推荐使用天数变量), 7天 = 7 * 24 * 3600 秒,过期自动删除
+binlog_expire_logs_seconds = 604800
+# 限制单个 binlog 文件的大小
+max_binlog_size = 500M

+ 56 - 0
ha/mysql80/conf/my2.cnf

@@ -0,0 +1,56 @@
+[mysqld]
+# --- 1. 基础网络与端口配置 ---
+user            = mysql
+port            = 3306
+bind-address    = 0.0.0.0
+mysqlx-port     = 33060
+mysqlx-bind-address = 0.0.0.0
+
+# --- 2. 目录路径配置 ---
+# 注意:容器内路径。确保 Docker volumes 挂载了这些位置
+datadir         = /var/lib/mysql
+log-error       = /var/log/mysql/error.log
+secure-file-priv= /var/lib/mysql-files
+
+# --- 3. 基础性能与存储引擎 ---
+default_storage_engine = InnoDB
+disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,EXAMPLE"
+
+# --- 4. 事务与复制核心配置 (MGR 强制要求) ---
+server_id               = 2
+gtid_mode               = ON
+enforce_gtid_consistency = ON
+binlog_format           = ROW
+log_slave_updates       = ON
+binlog_checksum         = NONE
+master_info_repository  = TABLE
+relay_log_info_repository = TABLE
+transaction_write_set_extraction = XXHASH64
+
+# --- 5. MGR (Group Replication) 专项配置 ---
+plugin_load_add         = 'group_replication.so'
+# 使用 loose- 前缀避免启动时的未知变量错误
+# 集群唯一标识 (必须是标准 UUID)
+loose-group_replication_group_name="235e4553-3508-46c2-b3a3-768fc0c829e2"
+# 节点间同步数据的通信地址(建议使用容器固定 IP)
+loose-group_replication_local_address = "192.168.0.212:33061"
+# 集群种子节点地址列表
+loose-group_replication_group_seeds   = "192.168.0.211:33061,192.168.0.212:33061,192.168.0.213:33061"
+# 启动行为
+loose-group_replication_start_on_boot = OFF
+loose-group_replication_bootstrap_group = OFF
+# 模式配置 (推荐单主模式)
+loose-group_replication_single_primary_mode = ON
+loose-group_replication_enforce_update_everywhere_checks = OFF
+
+# --- 6. 日志与超时优化 ---
+slow_query_log      = 1
+slow_query_log_file = /var/log/mysql/slow.log
+long_query_time     = 2
+interactive_timeout = 28800
+wait_timeout        = 28800
+
+# 限制 binlog 的总大小或保留天数(MySQL 8.0 推荐使用天数变量), 7天 = 7 * 24 * 3600 秒,过期自动删除
+binlog_expire_logs_seconds = 604800
+# 限制单个 binlog 文件的大小
+max_binlog_size = 500M

+ 56 - 0
ha/mysql80/conf/my3.cnf

@@ -0,0 +1,56 @@
+[mysqld]
+# --- 1. 基础网络与端口配置 ---
+user            = mysql
+port            = 3306
+bind-address    = 0.0.0.0
+mysqlx-port     = 33060
+mysqlx-bind-address = 0.0.0.0
+
+# --- 2. 目录路径配置 ---
+# 注意:容器内路径。确保 Docker volumes 挂载了这些位置
+datadir         = /var/lib/mysql
+log-error       = /var/log/mysql/error.log
+secure-file-priv= /var/lib/mysql-files
+
+# --- 3. 基础性能与存储引擎 ---
+default_storage_engine = InnoDB
+disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,EXAMPLE"
+
+# --- 4. 事务与复制核心配置 (MGR 强制要求) ---
+server_id               = 3
+gtid_mode               = ON
+enforce_gtid_consistency = ON
+binlog_format           = ROW
+log_slave_updates       = ON
+binlog_checksum         = NONE
+master_info_repository  = TABLE
+relay_log_info_repository = TABLE
+transaction_write_set_extraction = XXHASH64
+
+# --- 5. MGR (Group Replication) 专项配置 ---
+plugin_load_add         = 'group_replication.so'
+# 使用 loose- 前缀避免启动时的未知变量错误
+# 集群唯一标识 (必须是标准 UUID)
+loose-group_replication_group_name="235e4553-3508-46c2-b3a3-768fc0c829e2"
+# 节点间同步数据的通信地址(建议使用容器固定 IP)
+loose-group_replication_local_address = "192.168.0.213:33061"
+# 集群种子节点地址列表
+loose-group_replication_group_seeds   = "192.168.0.211:33061,192.168.0.212:33061,192.168.0.213:33061"
+# 启动行为
+loose-group_replication_start_on_boot = OFF
+loose-group_replication_bootstrap_group = OFF
+# 模式配置 (推荐单主模式)
+loose-group_replication_single_primary_mode = ON
+loose-group_replication_enforce_update_everywhere_checks = OFF
+
+# --- 6. 日志与超时优化 ---
+slow_query_log      = 1
+slow_query_log_file = /var/log/mysql/slow.log
+long_query_time     = 2
+interactive_timeout = 28800
+wait_timeout        = 28800
+
+# 限制 binlog 的总大小或保留天数(MySQL 8.0 推荐使用天数变量), 7天 = 7 * 24 * 3600 秒,过期自动删除
+binlog_expire_logs_seconds = 604800
+# 限制单个 binlog 文件的大小
+max_binlog_size = 500M

+ 13 - 0
ha/mysql80/conf/mysqlrouter.conf

@@ -0,0 +1,13 @@
+[DEFAULT]
+logging_folder=/var/log/mysqlrouter
+runtime_config_folder=/var/lib/mysqlrouter
+
+[routing:bootstrap_rw]
+bind_address=0.0.0.0:6446
+destinations=mysql80-1:3306,mysql80-2:3306,mysql80-3:3306
+routing_strategy=first-available
+
+[routing:bootstrap_ro]
+bind_address=0.0.0.0:6447
+destinations=mysql80-1:3306,mysql80-2:3306,mysql80-3:3306
+routing_strategy=round-robin

+ 74 - 0
ha/mysql80/create_user.sh

@@ -0,0 +1,74 @@
+#!/bin/bash
+
+##############################################################################
+# 在 mysql 和 proxysql 中同时创建用户
+##############################################################################
+
+# --- 配置区 ---
+# MySQL 管理员信息
+MYSQL_ADMIN="root"
+MYSQL_PASS="Root_123456"
+
+# ProxySQL 管理员信息
+PROXY_ADMIN="admin"
+PROXY_PASS="admin"
+PROXY_HOST="127.0.0.1"
+PROXY_PORT="6032"
+
+# 新用户信息
+NEW_USER=$1
+NEW_PASS=$2
+
+if [ -z "$NEW_USER" ] || [ -z "$NEW_PASS" ]; then
+    echo "使用方法: ./create_mgr_user.sh <用户名> <密码>"
+    exit 1
+fi
+
+echo ">>> 正在连接 ProxySQL 寻找当前的 Primary 节点..."
+# 获取 Hostgroup 10 中的第一个 ONLINE 节点
+PRIMARY_NODE=$(docker exec -i proxysql mysql -u$PROXY_ADMIN -p$PROXY_PASS -h$PROXY_HOST -P$PROXY_PORT -N -s -e "SELECT hostname FROM runtime_mysql_servers WHERE hostgroup_id=10 AND status='ONLINE' LIMIT 1;")
+
+if [ -z "$PRIMARY_NODE" ]; then
+    echo "错误: 无法在 ProxySQL 中找到在线的 Primary 节点!"
+    exit 1
+fi
+
+echo ">>> 发现 Primary 节点: $PRIMARY_NODE"
+
+# 1. 在 MySQL 中创建用户
+echo ">>> 步骤 1: 在 MySQL ($PRIMARY_NODE) 中创建用户..."
+docker exec -i $PRIMARY_NODE mysql -u$MYSQL_ADMIN -p$MYSQL_PASS <<EOF
+CREATE USER IF NOT EXISTS '$NEW_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$NEW_PASS';
+GRANT ALL PRIVILEGES ON *.* TO '$NEW_USER'@'%';
+FLUSH PRIVILEGES;
+EOF
+
+if [ $? -eq 0 ]; then
+    echo "√ MySQL 用户创建成功"
+else
+    echo "× MySQL 用户创建失败"
+    exit 1
+fi
+
+# 2. 在 ProxySQL 中登记用户
+echo ">>> 步骤 2: 在 ProxySQL 中同步用户信息..."
+docker exec -i proxysql mysql -u$PROXY_ADMIN -p$PROXY_PASS -h$PROXY_HOST -P$PROXY_PORT <<EOF
+-- 删除旧记录防止冲突
+DELETE FROM mysql_users WHERE username='$NEW_USER';
+-- 插入新用户,默认指向写组 10
+INSERT INTO mysql_users(username, password, default_hostgroup) VALUES ('$NEW_USER', '$NEW_PASS', 10);
+
+LOAD MYSQL USERS TO RUNTIME;
+SAVE MYSQL USERS TO DISK;
+EOF
+
+if [ $? -eq 0 ]; then
+    echo "√ ProxySQL 用户同步成功"
+else
+    echo "× ProxySQL 用户同步失败"
+    exit 1
+fi
+
+echo "------------------------------------------------"
+echo "恭喜!用户 $NEW_USER 已创建完毕。"
+echo "现在你可以尝试通过 Navicat 连接 127.0.0.1:6033 了。"

+ 98 - 0
ha/mysql80/docker-compose.yml

@@ -0,0 +1,98 @@
+services:
+  mysql80-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-1
+    hostname: mysql80-1
+    ports:
+      - "33061:3306"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql80a/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql80a/data:/var/lib/mysql
+      - /opt/docker/mysql80a/log:/var/log/mysql
+    healthcheck:
+      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}"]
+      interval: 5s
+      timeout: 5s
+      retries: 10
+    networks:
+      mgr-net:
+        ipv4_address: 172.20.0.11
+
+  mysql80-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-2
+    hostname: mysql80-2
+    ports:
+      - "33062:3306"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql80b/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql80b/data:/var/lib/mysql
+      - /opt/docker/mysql80b/log:/var/log/mysql
+    healthcheck:
+      test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}" ]
+      interval: 5s
+      timeout: 5s
+      retries: 10
+    depends_on:
+      mysql80-1:
+        condition: service_healthy
+    networks:
+      mgr-net:
+        ipv4_address: 172.20.0.12
+
+  mysql80-3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-3
+    hostname: mysql80-3
+    ports:
+      - "33063:3306"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql80c/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql80c/data:/var/lib/mysql
+      - /opt/docker/mysql80c/log:/var/log/mysql
+    healthcheck:
+      test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}" ]
+      interval: 5s
+      timeout: 5s
+      retries: 10
+    depends_on:
+      mysql80-2:
+        condition: service_healthy
+    networks:
+      mgr-net:
+        ipv4_address: 172.20.0.13
+
+  proxysql:
+    image: proxysql/proxysql:2.6.3
+    container_name: proxysql
+    restart: always
+    ports:
+      - "6032:6032" # 管理接口 (SQL 命令行配置)
+      - "6033:6033" # 业务访问接口 (应用连这里)
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+    healthcheck:
+      # 检查业务端口 6032 是否接受连接
+      test: [ "CMD", "mysql", "-uadmin", "-padmin", "-h127.0.0.1", "-P6032", "-e", "SELECT 1" ]
+      interval: 10s     # 每 10 秒检查一次
+      timeout: 5s       # 超时时间 5 秒
+      retries: 3        # 连续失败 3 次认为是不健康
+      start_period: 10s # 容器启动后给 10 秒缓冲时间再开始检查
+    networks:
+      mgr-net:
+        ipv4_address: 172.20.0.15
+networks:
+  mgr-net:
+    driver: bridge
+    ipam:
+      config:
+        - subnet: 172.20.0.0/24

+ 67 - 0
ha/mysql80/docker-compose1.yml

@@ -0,0 +1,67 @@
+services:
+  mysql80-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-1
+    hostname: mysql80-1
+    restart: always
+    ports:
+      - "3306:3306"
+      - "33061:33061"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql/data:/var/lib/mysql
+      - /opt/docker/mysql/log:/var/log/mysql
+    # 🚨 1. 容器日志限制:防止标准输出无节制增长
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"  # 单个日志文件最大 100M
+        max-file: "3"     # 最多保留 3 个归档文件
+    # 🚨 2. 资源限制与预留(生产环境建议:MySQL 单独占领一台机器,这里限制 2核4G 开销)
+    deploy:
+      resources:
+        limits:
+          cpus: '2.0'
+          memory: 4G
+        reservations:
+          cpus: '1.0'
+          memory: 2G
+    healthcheck:
+      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}"]
+      interval: 5s
+      timeout: 5s
+      retries: 10
+
+  proxysql:
+    image: proxysql/proxysql:2.6.3
+    container_name: proxysql
+    restart: always
+    ports:
+      - "6032:6032"
+      - "6033:6033"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+    # ProxySQL 日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "50m"
+        max-file: "3"
+    # ProxySQL 资源限制(作为转发层,日常消耗极低)
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: [ "CMD", "mysql", "-uadmin", "-padmin", "-h127.0.0.1", "-P6032", "-e", "SELECT 1" ]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+      start_period: 10s

+ 36 - 0
ha/mysql80/docker-compose2.yml

@@ -0,0 +1,36 @@
+services:
+  mysql80-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-2
+    hostname: mysql80-2
+    restart: always
+    ports:
+      - "3306:3306"
+      - "33061:33061"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql/data:/var/lib/mysql
+      - /opt/docker/mysql/log:/var/log/mysql
+    # 🚨 容器日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "3"
+    # 🚨 资源限制(与节点 1 保持严格对称)
+    deploy:
+      resources:
+        limits:
+          cpus: '2.0'
+          memory: 4G
+        reservations:
+          cpus: '1.0'
+          memory: 2G
+    healthcheck:
+      test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}" ]
+      interval: 5s
+      timeout: 5s
+      retries: 10

+ 36 - 0
ha/mysql80/docker-compose3.yml

@@ -0,0 +1,36 @@
+services:
+  mysql80-3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/mysql:8.0.36
+    container_name: mysql80-3
+    hostname: mysql80-3
+    restart: always
+    ports:
+      - "3306:3306"
+      - "33061:33061"
+    environment:
+      MYSQL_ROOT_PASSWORD: "Root_123456"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf
+      - /opt/docker/mysql/data:/var/lib/mysql
+      - /opt/docker/mysql/log:/var/log/mysql
+    # 🚨 容器日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "3"
+    # 🚨 资源限制(与节点 1、2 保持严格对称)
+    deploy:
+      resources:
+        limits:
+          cpus: '2.0'
+          memory: 4G
+        reservations:
+          cpus: '1.0'
+          memory: 2G
+    healthcheck:
+      test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}" ]
+      interval: 5s
+      timeout: 5s
+      retries: 10

+ 43 - 0
ha/mysql80/init_mgr.sh

@@ -0,0 +1,43 @@
+#!/bin/bash
+
+ROOT_PASS="Root_123456"
+MGR_USER="repl"
+MGR_PASS="Repl_123456"
+
+echo ">>> 正在执行 MySQL 8.0.36 专用初始化流程 (绕过通道锁定)..."
+
+for i in 1 2 3; do
+    echo "正在准备节点 mysql80-$i..."
+    docker exec -i mysql80-$i mysql -uroot -p${ROOT_PASS} <<EOF
+STOP GROUP_REPLICATION;
+RESET MASTER;
+
+SET SQL_LOG_BIN=0;
+CREATE USER IF NOT EXISTS '${MGR_USER}'@'%' IDENTIFIED WITH mysql_native_password BY '${MGR_PASS}';
+GRANT REPLICATION SLAVE ON *.* TO '${MGR_USER}'@'%';
+GRANT BACKUP_ADMIN ON *.* TO '${MGR_USER}'@'%';
+FLUSH PRIVILEGES;
+SET SQL_LOG_BIN=1;
+EOF
+done
+
+# 2. 引导主节点 (在 START 时直接传入凭证)
+echo ">>> 引导主节点 mysql80-1..."
+docker exec -i mysql80-1 mysql -uroot -p${ROOT_PASS} <<EOF
+SET GLOBAL group_replication_bootstrap_group=ON;
+START GROUP_REPLICATION USER='${MGR_USER}', PASSWORD='${MGR_PASS}';
+SET GLOBAL group_replication_bootstrap_group=OFF;
+EOF
+
+# 3. 加入从节点 (同样在 START 时传入凭证)
+for i in 2 3; do
+    echo ">>> 加入从节点 mysql80-$i..."
+    docker exec -i mysql80-$i mysql -uroot -p${ROOT_PASS} -e "
+      START GROUP_REPLICATION USER='${MGR_USER}', PASSWORD='${MGR_PASS}';
+    "
+done
+
+echo "----------------------------------------"
+docker exec -i mysql80-1 mysql -uroot -p${ROOT_PASS} -e "
+SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;
+"

+ 24 - 0
ha/mysql80/init_mysql80-1.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+
+###############################################################################
+# 初始化时使用, 只能执行一次
+###############################################################################
+
+echo "init mysql80-1..."
+base_dir="/opt/docker/mysql"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my1.cnf ${base_dir}/conf/my.cnf
+
+# 启动
+docker compose -f docker-compose1.yml up -d

+ 24 - 0
ha/mysql80/init_mysql80-2.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+
+###############################################################################
+# 初始化时使用, 只能执行一次
+###############################################################################
+
+echo "init mysql80-2..."
+base_dir="/opt/docker/mysql"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my2.cnf ${base_dir}/conf/my.cnf
+
+# 启动
+docker compose -f docker-compose2.yml up -d

+ 24 - 0
ha/mysql80/init_mysql80-3.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+
+###############################################################################
+# 初始化时使用, 只能执行一次
+###############################################################################
+
+echo "init mysql80-3..."
+base_dir="/opt/docker/mysql"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my3.cnf ${base_dir}/conf/my.cnf
+
+# 启动
+docker compose -f docker-compose3.yml up -d

+ 47 - 0
ha/mysql80/init_mysql80.sh

@@ -0,0 +1,47 @@
+#!/bin/bash
+
+set -e
+
+###############################################################################
+# 初始化时使用, 只能执行一次
+###############################################################################
+
+echo "init mysql80 cluster..."
+base_dir="/opt/docker/mysql80a"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my1.cnf ${base_dir}/conf/my.cnf
+
+base_dir="/opt/docker/mysql80b"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my2.cnf ${base_dir}/conf/my.cnf
+
+base_dir="/opt/docker/mysql80c"
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    sudo rm -rf ${base_dir}
+fi
+# 准备工作
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/conf
+mkdir ${base_dir}/log
+chmod -R go+w ${base_dir}
+cp conf/my3.cnf ${base_dir}/conf/my.cnf
+
+# 启动
+docker compose up -d

+ 84 - 0
ha/mysql80/init_proxysql.sh

@@ -0,0 +1,84 @@
+#!/bin/bash
+
+########################################################################################################################
+# 部署 proxysql 的节点上执行
+########################################################################################################################
+
+# 清空 proxysql 中的所有数据
+docker exec -it proxysql mysql -uadmin -padmin -h127.0.0.1 -P6032 -e"
+-- 进入管理终端或通过 docker exec 执行
+DELETE FROM mysql_servers;
+DELETE FROM mysql_users;
+DELETE FROM mysql_query_rules;
+DELETE FROM mysql_group_replication_hostgroups;
+-- 清理旧的统计信息和日志(可选)
+DELETE FROM monitor.mysql_server_connect_log;
+DELETE FROM monitor.mysql_server_group_replication_log;
+
+-- 立即生效并持久化(此时 ProxySQL 变成“白纸”一张)
+LOAD MYSQL SERVERS TO RUNTIME;
+LOAD MYSQL USERS TO RUNTIME;
+LOAD MYSQL QUERY RULES TO RUNTIME;
+SAVE MYSQL SERVERS TO DISK;
+SAVE MYSQL USERS TO DISK;
+SAVE MYSQL QUERY RULES TO DISK;
+"
+
+# 重新初始化 proxysql
+docker exec -i proxysql mysql -uadmin -padmin -h127.0.0.1 -P6032 <<EOF
+-- 1. 添加基础服务器信息(只需加入到一个默认组,MGR 模块会自动挪动它们)
+INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (10, 'mysql80-1', 3306);
+INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (10, 'mysql80-2', 3306);
+INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (10, 'mysql80-3', 3306);
+
+-- 2. 配置 MGR 自动切换规则 (注意 backup_writer_hostgroup 必填)
+INSERT INTO mysql_group_replication_hostgroups
+(writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, backup_writer_hostgroup)
+VALUES (10, 20, 30, 1, 1, 1, 40);
+
+-- 3. 配置业务访问账号 (应用连接用)
+INSERT INTO mysql_users(username, password, default_hostgroup) VALUES ('root', 'Root_123456', 10);
+
+-- 4. 设置监控凭证与开关
+UPDATE global_variables SET variable_value='root' WHERE variable_name='mysql-monitor_username';
+UPDATE global_variables SET variable_value='Root_123456' WHERE variable_name='mysql-monitor_password';
+-- 开启并加快监控频率
+UPDATE global_variables SET variable_value='1000' WHERE variable_name='mysql-monitor_group_replication_healthcheck_interval';
+
+-- 5. 一键加载
+LOAD MYSQL SERVERS TO RUNTIME;
+LOAD MYSQL USERS TO RUNTIME;
+LOAD MYSQL VARIABLES TO RUNTIME;
+SAVE MYSQL SERVERS TO DISK;
+SAVE MYSQL USERS TO DISK;
+SAVE MYSQL VARIABLES TO DISK;
+EOF
+
+# 验证配置结果
+docker exec -it proxysql mysql -uadmin -padmin -h127.0.0.1 -P6032 -e "
+SELECT hostgroup_id, hostname, status FROM runtime_mysql_servers;
+"
+
+# 添加路由规则
+docker exec -i proxysql mysql -uadmin -padmin -h127.0.0.1 -P6032 <<EOF
+-- 1. 清理旧规则
+DELETE FROM mysql_query_rules;
+
+-- 2. 规则 A:将所有 SELECT 语句路由到 HG 20 (读组)
+-- match_digest 是 SQL 指纹正则,apply=1 表示匹配到就执行,不再往下走
+INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
+VALUES (1, 1, '^SELECT.*', 20, 1);
+
+-- 3. 规则 B:显式锁定带 FOR UPDATE 的 SELECT 到 HG 10 (写组)
+-- 注意:这条规则的 rule_id 要比上一条小,或者优先级更高,防止被通配规则截获
+INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
+VALUES (2, 1, '^SELECT.*FOR UPDATE', 10, 1);
+
+-- 加载并持久化
+LOAD MYSQL QUERY RULES TO RUNTIME;
+SAVE MYSQL QUERY RULES TO DISK;
+EOF
+
+docker exec -i proxysql mysql -uadmin -padmin -h127.0.0.1 -P6032 -e"
+SELECT hostgroup_id, hostname, status FROM runtime_mysql_servers;
+"

+ 14 - 0
ha/mysql80/join_cluster.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+ROOT_PASS="Root_123456"
+MGR_USER="repl"
+MGR_PASS="Repl_123456"
+CONTAINER="mysql80-3"
+
+#docker exec -i ${CONTAINER} mysql -uroot -p${ROOT_PASS} -e "
+#  START GROUP_REPLICATION USER='${MGR_USER}', PASSWORD='${MGR_PASS}';
+#"
+
+docker exec -i mysql80-1 mysql -uroot -pRoot_123456  -e "
+SELECT * FROM performance_schema.replication_group_members;
+"

+ 31 - 0
ha/mysql80/mgr_bootstrap.sh

@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# 重新引导 MGR 集群, 这是集群重启后的典型状态
+
+# 根据 GTID 判断数据新旧
+docker exec -i mysql80-1 mysql -uroot -pRoot_123456  -e"
+SELECT @@global.gtid_executed;
+"
+
+docker exec -i mysql80-2 mysql -uroot -pRoot_123456  -e"
+SELECT @@global.gtid_executed;
+"
+
+docker exec -i mysql80-3 mysql -uroot -pRoot_123456  -e"
+SELECT @@global.gtid_executed;
+"
+
+# 假设 mysql80-1 节点的数据最新, 将其作为引导节点
+docker exec -i mysql80-1 mysql -uroot -pRoot_123456 -e "
+SET GLOBAL group_replication_bootstrap_group=ON;
+START GROUP_REPLICATION USER='repl', PASSWORD='Repl_123456';
+SET GLOBAL group_replication_bootstrap_group=OFF;
+"
+
+docker exec -i mysql80-2 mysql -uroot -pRoot_123456 -e "
+START GROUP_REPLICATION USER='repl', PASSWORD='Repl_123456';
+"
+
+docker exec -i mysql80-3 mysql -uroot -pRoot_123456 -e "
+START GROUP_REPLICATION USER='repl', PASSWORD='Repl_123456';
+"

+ 40 - 0
ha/rabbitmq/docker-compose-1.yml

@@ -0,0 +1,40 @@
+services:
+  rabbitmq:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/rabbitmq:3.13.7-management-alpine
+    container_name: rabbitmq
+    restart: always
+    hostname: node211 # 🚨 必须与物理机 hostname 一致
+    ports:
+      - "5672:5672"
+      - "15672:15672"
+      - "25672:25672" # 🚨 必须暴露:集群节点间通信端口
+      - "4369:4369"   # 🚨 必须暴露:EPMD 端口
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/rabbitmq/data:/var/lib/rabbitmq
+      - /opt/docker/rabbitmq/log:/var/log/rabbitmq
+    environment:
+      - RABBITMQ_DEFAULT_USER=test
+      - RABBITMQ_DEFAULT_PASS=Test_123456
+      # 🚨 核心:三台机器的 Erlang Cookie 必须完全串联一致
+      - RABBITMQ_ERLANG_COOKIE=SecretRabbitCookie2026
+      - RABBITMQ_VM_MEMORY_HIGH_WATERMARK_RELATIVE=0.4
+      - RABBITMQ_DISK_FREE_ABSOLUTE_LIMIT=2GB
+    # 让容器内也能识别三台机器的主机名
+    extra_hosts:
+      - "node211:192.168.0.211"
+      - "node212:192.168.0.212"
+      - "node213:192.168.0.213"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1024M
+        reservations:
+          cpus: '0.1'
+          memory: 512M
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "3"

+ 38 - 0
ha/rabbitmq/docker-compose-2.yml

@@ -0,0 +1,38 @@
+services:
+  rabbitmq:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/rabbitmq:3.13.7-management-alpine
+    container_name: rabbitmq
+    restart: always
+    hostname: node212 # 🚨 必须与物理机 hostname 一致
+    ports:
+      - "5672:5672"
+      - "15672:15672"
+      - "25672:25672"
+      - "4369:4369"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/rabbitmq/data:/var/lib/rabbitmq
+      - /opt/docker/rabbitmq/log:/var/log/rabbitmq
+    environment:
+      - RABBITMQ_DEFAULT_USER=test
+      - RABBITMQ_DEFAULT_PASS=Test_123456
+      - RABBITMQ_ERLANG_COOKIE=SecretRabbitCookie2026 # 🚨 保持一致
+      - RABBITMQ_VM_MEMORY_HIGH_WATERMARK_RELATIVE=0.4
+      - RABBITMQ_DISK_FREE_ABSOLUTE_LIMIT=2GB
+    extra_hosts:
+      - "node211:192.168.0.211"
+      - "node212:192.168.0.212"
+      - "node213:192.168.0.213"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1024M
+        reservations:
+          cpus: '0.1'
+          memory: 512M
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "3"

+ 38 - 0
ha/rabbitmq/docker-compose-3.yml

@@ -0,0 +1,38 @@
+services:
+  rabbitmq:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/rabbitmq:3.13.7-management-alpine
+    container_name: rabbitmq
+    restart: always
+    hostname: node213 # 🚨 必须与物理机 hostname 一致
+    ports:
+      - "5672:5672"
+      - "15672:15672"
+      - "25672:25672"
+      - "4369:4369"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/rabbitmq/data:/var/lib/rabbitmq
+      - /opt/docker/rabbitmq/log:/var/log/rabbitmq
+    environment:
+      - RABBITMQ_DEFAULT_USER=test
+      - RABBITMQ_DEFAULT_PASS=Test_123456
+      - RABBITMQ_ERLANG_COOKIE=SecretRabbitCookie2026 # 🚨 保持一致
+      - RABBITMQ_VM_MEMORY_HIGH_WATERMARK_RELATIVE=0.4
+      - RABBITMQ_DISK_FREE_ABSOLUTE_LIMIT=2GB
+    extra_hosts:
+      - "node211:192.168.0.211"
+      - "node212:192.168.0.212"
+      - "node213:192.168.0.213"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1024M
+        reservations:
+          cpus: '0.1'
+          memory: 512M
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "3"

+ 13 - 0
ha/rabbitmq/init_rabbitmq1.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+echo "init rabbitmq..."
+base_dir='/opt/docker/rabbitmq'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose1.yml up -d

+ 13 - 0
ha/rabbitmq/init_rabbitmq2.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+echo "init rabbitmq..."
+base_dir='/opt/docker/rabbitmq'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose2.yml up -d

+ 13 - 0
ha/rabbitmq/init_rabbitmq3.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+echo "init rabbitmq..."
+base_dir='/opt/docker/rabbitmq'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose3.yml up -d

+ 8 - 0
ha/rabbitmq/join_cluster.sh

@@ -0,0 +1,8 @@
+# node212 上执行
+docker exec -it rabbitmq /bin/sh -c "rabbitmqctl stop_app && rabbitmqctl join_cluster rabbit@node211 && rabbitmqctl start_app"
+
+# node213 上执行
+# docker exec -it rabbitmq /bin/sh -c "rabbitmqctl stop_app && rabbitmqctl join_cluster rabbit@node211 && rabbitmqctl start_app"
+
+# 查看集群状态
+docker exec -it rabbitmq rabbitmqctl cluster_status

+ 106 - 0
ha/redis/docker-compose.yml

@@ -0,0 +1,106 @@
+services:
+  # 主节点
+  redis-master:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-master
+    restart: always
+    command: redis-server /etc/redis/redis.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./redis/redis.conf:/etc/redis/redis.conf
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s      # 每 5 秒检查一次
+      timeout: 3s       # 超时时间
+      retries: 5        # 重试次数
+      start_period: 10s # 容器启动后 10 秒内不计入失败
+
+  # 从节点 1
+  redis-slave-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-slave-1
+    restart: always
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./redis/redis.conf:/etc/redis/redis.conf
+    command: redis-server /etc/redis/redis.conf --replicaof redis-master 6379
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s      # 每 5 秒检查一次
+      timeout: 3s       # 超时时间
+      retries: 5        # 重试次数
+      start_period: 10s # 容器启动后 10 秒内不计入失败
+    depends_on:
+      - redis-master
+
+  # 从节点 2
+  redis-slave-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-slave-2
+    restart: always
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./redis/redis.conf:/etc/redis/redis.conf
+    command: redis-server /etc/redis/redis.conf --replicaof redis-master 6379
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s      # 每 5 秒检查一次
+      timeout: 3s       # 超时时间
+      retries: 5        # 重试次数
+      start_period: 10s # 容器启动后 10 秒内不计入失败
+    depends_on:
+      - redis-master
+
+  # 哨兵 1
+  sentinel-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-1
+    restart: always
+    ports:
+      - "26379:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./sentinel/sentinel1.conf:/etc/redis/sentinel.conf
+    healthcheck:
+      # 哨兵端口不同,需要指定端口进行 ping
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5
+
+  # 哨兵 2
+  sentinel-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-2
+    restart: always
+    ports:
+      - "26380:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./sentinel/sentinel2.conf:/etc/redis/sentinel.conf
+    healthcheck:
+      # 哨兵端口不同,需要指定端口进行 ping
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5
+
+  # 哨兵 3
+  sentinel-3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-3
+    restart: always
+    ports:
+      - "26381:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ./sentinel/sentinel3.conf:/etc/redis/sentinel.conf
+    healthcheck:
+      # 哨兵端口不同,需要指定端口进行 ping
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5

+ 63 - 0
ha/redis/docker-compose1.yml

@@ -0,0 +1,63 @@
+services:
+  redis-master:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-master
+    restart: always
+    ports:
+      - "6379:6379"
+    # 开启 AOF 持久化(生产环境建议开启)
+    command: redis-server /etc/redis/redis.conf --appendonly yes
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/redis.conf:/etc/redis/redis.conf
+      - /opt/docker/redis/data:/data
+    # 🚨 容器日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "50m"
+        max-file: "3"
+    # 🚨 从节点资源限制(与主节点保持完全一致,以便故障转移后能完美顶上)
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 2G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5
+      start_period: 10s
+
+  sentinel-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-1
+    restart: always
+    ports:
+      - "26379:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/sentinel/sentinel.conf:/etc/redis/sentinel.conf
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "20m"
+        max-file: "3"
+    deploy:
+      resources:
+        limits:
+          cpus: '0.5'
+          memory: 512M
+        reservations:
+          cpus: '0.2'
+          memory: 256M
+    healthcheck:
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5

+ 63 - 0
ha/redis/docker-compose2.yml

@@ -0,0 +1,63 @@
+services:
+  redis-slave-1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-slave-1
+    restart: always
+    ports:
+      - "6379:6379"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/redis.conf:/etc/redis/redis.conf
+      - /opt/docker/redis/data:/data
+    # 🚨 容器日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "50m"
+        max-file: "3"
+    # 🚨 从节点资源限制(与主节点保持完全一致,以便故障转移后能完美顶上)
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 2G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    # 同样建议开启从节点的 AOF
+    command: redis-server /etc/redis/redis.conf --replicaof 192.168.0.211 6379 --appendonly yes
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5
+      start_period: 10s
+
+  sentinel-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-2
+    restart: always
+    ports:
+      - "26379:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/sentinel/sentinel.conf:/etc/redis/sentinel.conf
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "20m"
+        max-file: "3"
+    deploy:
+      resources:
+        limits:
+          cpus: '0.5'
+          memory: 512M
+        reservations:
+          cpus: '0.2'
+          memory: 256M
+    healthcheck:
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5

+ 62 - 0
ha/redis/docker-compose3.yml

@@ -0,0 +1,62 @@
+services:
+  redis-slave-2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: redis-slave-2
+    restart: always
+    ports:
+      - "6379:6379"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/redis.conf:/etc/redis/redis.conf
+      - /opt/docker/redis/data:/data
+    # 🚨 容器日志限制
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "50m"
+        max-file: "3"
+    # 🚨 从节点资源限制(与主节点保持完全一致,以便故障转移后能完美顶上)
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 2G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    command: redis-server /etc/redis/redis.conf --replicaof 192.168.0.211 6379 --appendonly yes
+    healthcheck:
+      test: [ "CMD", "redis-cli", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5
+      start_period: 10s
+
+  sentinel-3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/redis:6.0.16-bullseye
+    container_name: sentinel-3
+    restart: always
+    ports:
+      - "26379:26379"
+    command: redis-sentinel /etc/redis/sentinel.conf
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - /opt/docker/redis/sentinel/sentinel.conf:/etc/redis/sentinel.conf
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "20m"
+        max-file: "3"
+    deploy:
+      resources:
+        limits:
+          cpus: '0.5'
+          memory: 512M
+        reservations:
+          cpus: '0.2'
+          memory: 256M
+    healthcheck:
+      test: [ "CMD", "redis-cli", "-p", "26379", "ping" ]
+      interval: 5s
+      timeout: 3s
+      retries: 5

+ 17 - 0
ha/redis/init_redis1.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "init redis..."
+base_dir='/opt/docker/redis'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/sentinel
+chmod -R go+w ${base_dir}
+
+cp redis/redis.conf ${base_dir}/redis.conf
+cp redis/sentinel/sentinel1.conf ${base_dir}/sentinel.conf
+
+docker compose -f docker-compose1.yml up -d

+ 17 - 0
ha/redis/init_redis2.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "init redis..."
+base_dir='/opt/docker/redis'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/sentinel
+chmod -R go+w ${base_dir}
+
+cp redis/redis.conf ${base_dir}/redis.conf
+cp redis/sentinel/sentinel2.conf ${base_dir}/sentinel.conf
+
+docker compose -f docker-compose2.yml up -d

+ 17 - 0
ha/redis/init_redis3.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "init redis..."
+base_dir='/opt/docker/redis'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/sentinel
+chmod -R go+w ${base_dir}
+
+cp redis/redis.conf ${base_dir}/redis.conf
+cp redis/sentinel/sentinel3.conf ${base_dir}/sentinel.conf
+
+docker compose -f docker-compose3.yml up -d

+ 9 - 0
ha/redis/redis/redis.conf

@@ -0,0 +1,9 @@
+# 允许远程连接
+bind 0.0.0.0
+# 关闭保护模式
+protected-mode no
+
+# 推荐设为 1.5G 左右(小于 2G)
+maxmemory 1500mb
+# 或者是 allkeys-lru,根据业务选择淘汰过期键或所有键
+maxmemory-policy volatile-lru

+ 8 - 0
ha/redis/sentinel/sentinel1.conf

@@ -0,0 +1,8 @@
+port 26379
+dir /tmp
+# 监控主节点,名称为 mymaster,2 表示至少需要 2 个哨兵同意才能进行故障转移
+sentinel monitor mymaster 192.168.0.211 6379 2
+# 主节点失联 5s 则认为下线
+sentinel down-after-milliseconds mymaster 5000
+# 故障转移超时时间
+sentinel failover-timeout mymaster 10000

+ 8 - 0
ha/redis/sentinel/sentinel2.conf

@@ -0,0 +1,8 @@
+port 26379
+dir /tmp
+# 监控主节点,名称为 mymaster,2 表示至少需要 2 个哨兵同意才能进行故障转移
+sentinel monitor mymaster 192.168.0.211 6379 2
+# 主节点失联 5s 则认为下线
+sentinel down-after-milliseconds mymaster 5000
+# 故障转移超时时间
+sentinel failover-timeout mymaster 10000

+ 8 - 0
ha/redis/sentinel/sentinel3.conf

@@ -0,0 +1,8 @@
+port 26379
+dir /tmp
+# 监控主节点,名称为 mymaster,2 表示至少需要 2 个哨兵同意才能进行故障转移
+sentinel monitor mymaster 192.168.0.211 6379 2
+# 主节点失联 5s 则认为下线
+sentinel down-after-milliseconds mymaster 5000
+# 故障转移超时时间
+sentinel failover-timeout mymaster 10000

+ 30 - 0
ha/zookeeper/docker-compose-1.yml

@@ -0,0 +1,30 @@
+services:
+  zk1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4
+    restart: always
+    hostname: node211
+    container_name: zk1
+    ports:
+      - "2181:2181"
+      - "2888:2888"
+      - "3888:3888"
+    volumes:
+      - /opt/docker/zookeeper/data:/data
+      - /opt/docker/zookeeper/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 1
+      ZOO_SERVERS: server.1=192.168.0.211:2888:3888;2181 server.2=192.168.0.212:2888:3888;2181 server.3=192.168.0.213:2888:3888;2181
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3

+ 30 - 0
ha/zookeeper/docker-compose-2.yml

@@ -0,0 +1,30 @@
+services:
+  zk2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4
+    restart: always
+    hostname: node212
+    container_name: zk2
+    ports:
+      - "2181:2181"
+      - "2888:2888"
+      - "3888:3888"
+    volumes:
+      - /opt/docker/zookeeper/data:/data
+      - /opt/docker/zookeeper/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 2
+      ZOO_SERVERS: server.1=192.168.0.211:2888:3888;2181 server.2=192.168.0.212:2888:3888;2181 server.3=192.168.0.213:2888:3888;2181
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3

+ 30 - 0
ha/zookeeper/docker-compose-3.yml

@@ -0,0 +1,30 @@
+services:
+  zk3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4
+    restart: always
+    hostname: node213
+    container_name: zk3
+    ports:
+      - "2181:2181"
+      - "2888:2888"
+      - "3888:3888"
+    volumes:
+      - /opt/docker/zookeeper/data:/data
+      - /opt/docker/zookeeper/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 3
+      ZOO_SERVERS: server.1=192.168.0.211:2888:3888;2181 server.2=192.168.0.212:2888:3888;2181 server.3=192.168.0.213:2888:3888;2181
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3

+ 79 - 0
ha/zookeeper/docker-compose.yml

@@ -0,0 +1,79 @@
+services:
+  zoo1:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4 # 生产环境建议锁定具体版本
+    restart: always
+    hostname: zoo1
+    container_name: zoo1
+    ports:
+      - "2181:2181"
+    volumes:
+      - ./data/zoo1/data:/data
+      - ./data/zoo1/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 1
+      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
+      # 限制 JVM 内存,通常设为容器限制的 70-80%
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+        reservations:
+          cpus: '0.5'
+          memory: 512M
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+
+  zoo2:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4
+    restart: always
+    hostname: zoo2
+    container_name: zoo2
+    ports:
+      - "2182:2181"
+    volumes:
+      - ./data/zoo2/data:/data
+      - ./data/zoo2/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 2
+      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+
+  zoo3:
+    image: registry.cn-chengdu.aliyuncs.com/reghao/zookeeper:3.8.4
+    restart: always
+    hostname: zoo3
+    container_name: zoo3
+    ports:
+      - "2183:2181"
+    volumes:
+      - ./data/zoo3/data:/data
+      - ./data/zoo3/datalog:/datalog
+    environment:
+      ZOO_MY_ID: 3
+      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
+      JVMFLAGS: "-Xms512m -Xmx512m"
+    deploy:
+      resources:
+        limits:
+          cpus: '1.0'
+          memory: 1G
+    healthcheck:
+      test: ["CMD-SHELL", "echo ruok | nc localhost 2181 | grep imok"]
+      interval: 10s
+      timeout: 5s
+      retries: 3

+ 14 - 0
ha/zookeeper/init_zk1.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+echo "init zookeeper..."
+base_dir='/opt/docker/zookeeper'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/datalog
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose1.yml up -d

+ 14 - 0
ha/zookeeper/init_zk2.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+echo "init zookeeper..."
+base_dir='/opt/docker/zookeeper'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/datalog
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose2.yml up -d

+ 14 - 0
ha/zookeeper/init_zk3.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+echo "init zookeeper..."
+base_dir='/opt/docker/zookeeper'
+if [ -d ${base_dir} ]; then
+    echo ${base_dir}"已存在, 删除后重新创建..."
+    rm -rf ${base_dir}
+fi
+
+mkdir -p ${base_dir}/data
+mkdir ${base_dir}/datalog
+chmod -R go+w ${base_dir}
+
+docker compose -f docker-compose3.yml up -d