Skip to content

运维-扩展服务

1. APC安装指南

目前改善 PHP 性能的主流技术体系,已经不再推荐使用 APC 或 eAccelerator,而是全面转向以下现代化、高性能、高稳定性的方案:

1. Opcache(Zend Opcache) – 官方主力推荐

简介:

  • 从 PHP 5.5 起默认内置,不再需要单独安装扩展;
  • 由 Zend 官方开发,替代了 APC 的 Opcode 缓存功能;
  • 支持预加载(PHP 7.4+)、优化 opcode 执行路径、并支持多线程共享内存。

优势:

  • 性能最高:Zend 官方内建,几乎为所有 PHP 安装默认启用;
  • 兼容性强:兼容主流框架(Laravel、Symfony)、CMS(WordPress、Discuz!);
  • 安全可靠:代码优化与 opcode 校验机制更健壮。

2. PHP-FPM 配置优化(FastCGI Process Manager)

  • 使用 静态/动态进程池管理,可避免进程频繁创建/销毁带来的开销;
  • 调整 pm.max_children、pm.start_servers、pm.max_requests 可提升并发能力;
  • 与 Opcache 配合使用效果极佳。

3. 数据缓存:使用 Redis / Memcached

推荐方式:

  • 使用 Redis / Memcached 替代 APCu 进行 用户数据缓存;
  • 例如:登录态、权限缓存、SQL 查询缓存等;
  • 支持集群、高可用、数据持久化等特性。

4. 框架级缓存机制

  • Laravel、Symfony、ThinkPHP 等现代框架内建多级缓存支持(文件、Redis、数据库);
  • Discuz! X3.5 本身也支持切换缓存驱动(如 memory.php 配置文件中切换为 Redis);
  • 实际部署中建议将常用缓存(如模板缓存、配置缓存)迁移到内存型服务中。
功能类型 推荐技术 说明
Opcode 缓存 Opcache PHP 官方维护,取代 APC
数据缓存 Redis 替代 APCu,支持更多场景
会话/共享内存 Redis / Memcached 跨进程共享缓存首选
Web 服务器性能 PHP-FPM 优化 + Nginx 保持请求处理高并发

2. MySQL主从设置

进行 MySQL 主从配置(Replication) 的目的主要是为了解决 性能瓶颈、数据安全、扩展性 三个方面的问题,尤其是在高并发网站(如 Discuz!)部署中尤为重要。

以下是从架构、运维和性能三个维度讲解为什么要配置 MySQL 主从:

1. 读写分离 – 提升性能

说明:

  • 在 MySQL 主从架构中,主库(Master)负责写操作,如:发帖、注册、评论等;
  • 从库(Slave)负责读操作,如:访问帖子、浏览列表、查看用户资料等。

优势:

  • 将查询压力分散到多个从库,避免主库 CPU 和 I/O 过载;
  • 支持横向扩展,从库可根据访问量增加节点(负载均衡);
  • 在 Discuz! 中开启“读写分离”可直接利用这一优势。

2. 数据冗余 – 提高安全性

说明:

  • 从库保存主库的实时备份副本;
  • 即使主库数据损坏或丢失,也可以从从库中恢复。

优势:

  • 提高灾难恢复能力(Disaster Recovery);
  • 支持定点恢复(通过 binlog 和 position);
  • 可搭配 延迟复制 防止误操作(例如删库)同步。

3. 支持热备 – 不中断业务地进行维护

说明:

  • 在从库上做备份,不影响主库写入;
  • 可在从库进行复杂查询、分析、统计任务。

优势:

  • 避免主库锁表、影响在线用户体验;
  • 支持更平滑的数据库升级、迁移或大表维护。

4. 便于扩展和分布式部署

说明:

  • 可以为每个地理区域、业务模块设置多个从库;
  • 支持分布式查询、跨机房部署、读流量就近调度。

5. 总结:Discuz! 项目的数据库部署推荐方案(2025年版)

网站规模 推荐部署形式
小型站点 单实例 MySQL + Redis 缓存
中等站点 主从部署(1 主 N 从)+ Redis + 读写分离
高并发社区论坛 MGR 高可用主集群 + 多只读节点 + Redis + 分库表策略
企业私有部署 可考虑 TiDB(MySQL 协议兼容)或 Vitess(逻辑分布式)

6. MySQL 主库(Master)配置

# 编辑主库配置文件
vi /etc/my.cnf  # 打开 MySQL 主配置文件,通常路径为 /etc/my.cnf 或 /etc/mysql/my.cnf

[mysqld] 部分添加以下内容(确保无重复项):

log-bin=mysql-bin  # 启用二进制日志功能,是主从复制的基础
server-id=1  # 主服务器唯一 ID,不能与从库重复
binlog-do-db=dzx2  # 指定要复制的数据库,避免复制所有数据库
expire-logs-days=7  # 设置二进制日志保留 7 天,防止磁盘被日志占满

创建复制账户:

mysql -uroot -p  # 登录主库 MySQL 控制台
GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.1.3' IDENTIFIED BY '123';  # 授权从库使用复制账号连接主库

重启 MySQL 服务以应用配置:

systemctl restart mysqld  # 重启 MySQL 服务,或使用 service mysqld restart

7. 复制数据前,锁表并获取主库同步位置

mysql -uroot -p  # 登录 MySQL 控制台
FLUSH TABLES WITH READ LOCK;  # 锁定所有表以保持备份一致性
SHOW MASTER STATUS;  # 获取当前二进制日志文件名和位置,需记录 file 和 position

保持当前窗口打开,不要执行 UNLOCK TABLES,直到完成备份

执行备份操作(任选一种):

mysqldump -uroot -p --single-transaction --databases dzx2 > dzx2.sql  # 使用 mysqldump 导出数据
# 或者直接复制数据库文件(需关闭 MySQL)

解锁表并恢复正常服务:

UNLOCK TABLES;  # 解锁表,恢复写操作
exit  # 退出 mysql 控制台

恢复论坛访问:

# 登录 Discuz! 后台 -> 全局 -> 站点信息 -> 开放论坛访问

8. 从库(Slave)配置

# 编辑从库配置文件
vi /etc/my.cnf  # 打开从库的 MySQL 配置文件

[mysqld] 部分添加以下内容:

server-id=2  # 从库的唯一 ID,与主库不同
master-port=3306  # 主库监听的端口(默认 3306)
replicate-do-db=dzx2  # 需要复制的数据库
replicate-ignore-table=dzx2.pre_common_session  # 排除无意义的临时表(如会话表)
slave-skip-errors=1032,1062,126,1114,1146,1048,1396  # 自动跳过常见错误,防止复制中断

重启从库 MySQL:

systemctl restart mysqld  # 重启 MySQL 以应用配置

恢复主库备份数据:

mysql -uroot -p < dzx2.sql  # 恢复从主库导出的 SQL 数据

配置主从连接参数:

mysql -uroot -p  # 登录从库控制台
CHANGE MASTER TO 
  MASTER_HOST='192.168.1.2',  # 主库 IP
  MASTER_USER='rep',  # 主库创建的复制账户
  MASTER_PASSWORD='123',  # 复制账户密码
  MASTER_LOG_FILE='mysql-bin.000001',  # 主库记录的日志文件名
  MASTER_LOG_POS=154;  # 主库记录的 POS 位置,注意无引号

启动从库复制线程:

START SLAVE;  # 启动 IO 和 SQL 线程以开始复制
SHOW SLAVE STATUS\G;  # 检查 Slave_IO_Running 和 Slave_SQL_Running 是否为 Yes

补充(可选):my.cnf 设置简化连接信息(部分 MySQL 版本支持)

master-host=192.168.1.2  # 设置主库 IP
master-user=rep  # 主库复制账户
master-password=123  # 密码

9. Discuz! 中的读写分离配置

$_config['db']['slave']['1']['dbhost'] = '192.168.1.3';  # 从库 IP
$_config['db']['slave']['1']['dbuser'] = 'rep';  # 从库连接用户名
$_config['db']['slave']['1']['dbpw']   = '123';  # 密码
$_config['db']['slave']['1']['dbcharset'] = 'utf8';
$_config['db']['slave']['1']['pconnect'] = 0;
$_config['db']['slave']['1']['dbport'] = 3306;
$_config['db']['slave']['1']['weight'] = 1;  # 权重,数值越大被调度概率越高

3. Discuz! X2.5读写分离

// 打开 Discuz! 配置文件
config/config_global.php  # Discuz! 全局配置文件路径,读写分离参数位于此处

1. 配置读写分离的排除表

$_config['db']['common']['slave_except_table'] = 'common_session';  # 指定哪些表不使用从库读取,防止因同步延迟导致登录状态异常

架构说明:

  • common_session 是用户会话表,频繁读写,存在主从同步延迟风险;
  • 若未排除,用户登录后会出现“未登录”或“掉线”现象。

2. 配置第一个从库信息

$_config['db']['slave']['1']['dbhost'] = '192.168.1.2';  # 第一个从库的 IP 地址或主机名
$_config['db']['slave']['1']['dbuser'] = 'root';  # 从库连接用户名,应具备只读权限
$_config['db']['slave']['1']['dbpw'] = 'password';  # 数据库密码(生产环境应使用只读账户)
$_config['db']['slave']['1']['dbcharset'] = 'gbk';  # 数据库字符集,需与主库保持一致(常见为 utf8 或 gbk)
$_config['db']['slave']['1']['pconnect'] = '0';  # 是否启用持久连接,建议关闭以避免连接泄露
$_config['db']['slave']['1']['dbname'] = 'discuz';  # 目标数据库名称
$_config['db']['slave']['1']['tablepre'] = 'pre_';  # 表前缀,需与主库一致

架构说明:
- Discuz! 会根据内置的 slave_except_table 和数据操作类型(SELECT vs INSERT/UPDATE)动态决定是否使用从库;
- 多个从库将使用 轮询调度策略,可通过 weight 参数配置优先级(在 X3 之后支持)。


3. 如需添加第二个从库,继续追加如下配置

$_config['db']['slave']['2']['dbhost'] = '192.168.1.3';  # 第二个从库的 IP
$_config['db']['slave']['2']['dbuser'] = 'root';  # 用户名,通常与主库相同
$_config['db']['slave']['2']['dbpw'] = 'password';  # 密码
$_config['db']['slave']['2']['dbcharset'] = 'gbk';  # 字符集,与主库保持一致
$_config['db']['slave']['2']['pconnect'] = '0';  # 持久连接开关,建议设为 0
$_config['db']['slave']['2']['dbname'] = 'discuz';  # 数据库名
$_config['db']['slave']['2']['tablepre'] = 'pre_';  # 表前缀

调度说明:
- 当配置多个从库时,Discuz! 默认在其间轮询调度;
- 若需按访问量自动分配,可升级到 X3+ 并使用 weight 参数配置负载分担比例。


4. 修改完成后保存文件,系统会自动启用读写分离,无需额外操作。


补充说明:读写分离的适用条件与风险控制

条件 是否必须 原因说明
主从已配置完成 从库必须能同步主库数据,否则查询数据会不一致
时间同步准确 防止从库落后于主库太多,影响论坛用户体验
会话、缓存排除 推荐将如 common_session 及临时表排除,避免不一致
数据库字符集统一 字符集不一致可能导致乱码或查询失败
使用 Redis 缓存 推荐 可降低主库写压力,减少读写分离同步延迟风险

4. Discuz! X2.5安全配置指引

1. 系统安装阶段安全配置

# 推荐最小化安装系统
# 安装过程软件包选择:全部不选,仅安装最小化系统(无 GUI),降低攻击面

# 设置 root 密码
# 密码必须 ≥ 8 位,包含大小写、数字、符号,提高破解成本

# 精简服务,关闭无用或高危服务
chkconfig kudzu off          # 关闭硬件变更探测服务
chkconfig cpuspeed off       # 节能控制,服务器不推荐使用
chkconfig isdn off           # ISDN 拨号服务
chkconfig portmap off        # RPC 映射器,NFS 用到,默认关闭
chkconfig nfslock off        # NFS 文件锁支持
chkconfig rpcidmapd off      # RPC id 映射守护进程
chkconfig rpcgssd off        # RPC 安全认证支持
chkconfig bluetooth off      # 蓝牙服务
chkconfig netfs off          # 挂载网络文件系统
chkconfig pcscd off          # 智能卡支持服务
chkconfig apmd off           # 电源管理(APM)
chkconfig hidd off           # 蓝牙鼠标支持
chkconfig autofs off         # 自动挂载服务
chkconfig hplip off          # HP 打印机服务
chkconfig cups off           # 打印服务
chkconfig gpm off            # 控制台鼠标服务
chkconfig xfs off            # 字体服务
chkconfig avahi-daemon off   # 本地网络自动发现服务(类似 Bonjour)
chkconfig yum-updatesd off   # yum 自动更新守护进程
chkconfig firstboot off      # 安装后首次启动配置
chkconfig haldaemon off      # 硬件抽象层

# 数据挂载加强安全性
# 对 /home 或 /data 分区使用挂载选项 nodev,nosuid,nosetuid,禁止执行权限和设备节点
mount -o remount,nodev,nosuid,nosetuid /home  # 示例挂载调整命令

# 设置所有服务脚本权限为 root:root 且 755
chmod 755 /etc/init.d/* && chown root:root /etc/init.d/*  # 防止服务脚本被篡改

# 端口限制
# Web服务器:仅开放 80(HTTP) 和 22(SSH)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT  # 开放 HTTP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT  # 开放 SSH

# 数据库服务器:仅开放 3306(MySQL) 和 22(SSH)
iptables -A INPUT -p tcp --dport 3306 -j ACCEPT  # 仅内网访问
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 非核心端口应封闭,或设定特定 IP 白名单
iptables -A INPUT -p udp --dport 161 -s 10.0.0.0/8 -j ACCEPT  # SNMP
iptables -A INPUT -p tcp --dport 5666 -s 10.0.0.0/8 -j ACCEPT  # NRPE

# 禁止 FTP 服务(明文传输不安全)
chkconfig vsftpd off  # 关闭 vsftpd 服务

# 禁止任何服务使用 root 账户运行
# 建议创建独立账户运行:如 www、mysql、redis 等

# 内核安全设置(/etc/sysctl.conf)
echo "net.ipv4.tcp_syncookies = 1" >> /etc/sysctl.conf  # 防止 SYN Flood 攻击
echo "net.ipv4.conf.all.log_martians = 1" >> /etc/sysctl.conf  # 记录可疑 ARP 数据包
sysctl -p  # 应用内核参数

2. PHP 配置加强(php.ini)

disable_functions=passthru,exec,system,chroot,scandir,chgrp,chown,escapeshellcmd,escapeshellarg,shell_exec,proc_get_status,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,leak,popepassthru,stream_socket_server,popen  # 禁用所有危险函数,防止命令执行漏洞
register_globals = Off  # 防止全局变量覆盖漏洞
cgi.fix_pathinfo = 0  # 防止 Nginx + PHP 的路径解析漏洞
magic_quotes_gpc = On  # 自动对 GPC 输入进行转义,防止 SQL 注入(已废弃特性)
allow_url_include = Off  # 禁止远程文件包含漏洞
expose_php = Off  # 禁止暴露 PHP 版本,防止指纹识别

3. 数据库安全

# 单机部署 MySQL 时,仅绑定本地地址
bind-address = 127.0.0.1  # 防止外网连接数据库

# 多服务器部署时仅绑定内网地址
bind-address = 192.168.1.10  # 仅内网可连

# 每个站点使用独立 php-fpm 池,运行在独立用户下
# /etc/php-fpm.d/site1.conf 中:
user = www_site1  # 站点1专用用户
group = www_site1

# 每个服务使用独立用户运行
useradd -r www  # Web 服务用户
useradd -r mysql  # MySQL 用户
useradd -r redis  # Redis 用户
useradd -r memcache  # Memcached 用户

4. Discuz! 站点目录安全加固

# 探针与管理工具必须临时性使用
rm -f /var/www/html/phpinfo.php  # 删除探针文件
mv phpMyAdmin/ /root/phpMyAdmin_backup  # 管理程序移出 Web 根目录

# 禁止站点目录中存在 bak、old、test 目录或文件
find /var/www/html -type d -name "*bak*" -exec rm -rf {} \;  # 删除备份目录
find /var/www/html -type f -name "*.tar" -o -name "*.zip" -o -name "*.tar.gz" -exec rm -f {} \;  # 删除压缩包

# 删除 install、upgrade、xconvert 等敏感目录
rm -rf install/ upgrade/ xconvert/  # 清除残留升级脚本

# 清理编辑器自动备份文件
find /var/www/html -type f -name "*.swp" -o -name "*.bak" -exec rm -f {} \;

# 设置除以下目录外,其余目录仅允许 root 修改
chown -R root:root /var/www/html/
chmod -R 755 /var/www/html/

chown -R www:www /var/www/html/config/  # 允许 web 写入的目录
chown -R www:www /var/www/html/data/
chown -R www:www /var/www/html/uc_client/data/
chown -R www:www /var/www/html/uc_server/data/

# 禁止访问敏感目录下的 PHP 文件(以 Nginx 为例)
# /etc/nginx/conf.d/discuz.conf 中添加:
location ~ ^/(config|data|uc_client/data|uc_server/data)/.*\.php$ {
    deny all;  # 拒绝直接访问这些目录下的 PHP 文件
}

5. 总结:Discuz! 安全部署三层策略

层级 策略关键点
系统层 关闭不必要服务、限制端口、配置内核安全参数
PHP/MySQL层 禁用危险函数、限制访问地址、独立用户执行
应用层 清除敏感文件、隔离目录权限、Nginx 层禁止访问敏感脚本