深浅模式
config.yaml 配置详解
config.yaml 是灵萌后端服务启动时读取的配置文件,位于项目根目录(与可执行文件同级)。它决定服务怎么连数据库、怎么限流、定时任务多久跑一次、日志保留几天等基础设施行为。
修改后必须重启
config.yaml 里的改动不会热更新,改完后需要重启 Go 进程(或 systemd / Docker 容器)才会生效。
与「管理后台系统配置」的区别
| 配置来源 | 文件 / 入口 | 谁改 | 典型内容 |
|---|---|---|---|
| 启动级 | 根目录 config.yaml | 运维 / 开发 | 数据库、Redis、JWT、限流、定时任务 |
| 运行期 | 管理后台 → 系统设置 → 系统配置 | 运营 | 微信 AppID、支付商户号、短信、地图 Key |
本文档只讲 config.yaml。后台各 Tab 说明见 系统配置总览。
文件从哪里来?
- 首次启动:若根目录没有
config.yaml,程序会把内置模板default_config.yaml复制一份出来。 - 每次启动:现有
config.yaml会与内置模板自动对齐——补全新增字段、删除已废弃字段,你手改的值会保留。 - 初始化向导:访问
/setup完成后,数据库、Redis、JWT 等敏感项会写入config.yaml。
配置总览(按重要性)
| 配置块 | 一句话说明 | 生产必配 |
|---|---|---|
app | 端口、域名、环境、雪花 ID | 是 |
database | MySQL 连接与分库分表 | 是 |
redis | 缓存、队列、限流、分布式锁 | 是 |
jwt / security | 登录令牌与敏感数据加密 | 是 |
server | HTTP 超时、API 前缀、请求体大小 | 建议 |
task | 定时任务开关、清理天数、各任务周期 | 建议 |
cors | 跨域白名单 | 是 |
rate_limit | 全站接口防刷 | 建议 |
log | 日志目录、慢请求、轮转 | 建议 |
queue | 异步任务消费者 | 是 |
meilisearch / gorse / nebula | 搜索与推荐外部服务 | 按需 |
recommend | 推荐算法参数 | 按需 |
health_center / prometheus / tracing | 监控与自愈 | 按需 |
app — 应用基础
控制服务叫什么、监听哪个端口、对外域名是什么。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name | 字符串 | lingmeng | 服务名称,用于日志标识、追踪 service_name 兜底等 |
version | 字符串 | 2.0.0 | 历史遗留展示字段,实际运行版本以编译注入为准 |
env | 字符串 | prod | 运行环境:prod 会启用更严格校验;本地开发请设为 local |
port | 数字 | 8080 | HTTP 监听端口 |
domain | 字符串 | http://localhost:8080 | 对外访问地址(含 https://),用于生成回调链接、分享链接等 |
setup_completed | 布尔 | false | 是否完成 /setup 初始化向导;未完成会引导去配置 |
worker_id | 数字 0~1023 | 自动分配 | 雪花 ID 生成器的机器编号;多实例裸机部署建议每台不同 |
instance_id | 字符串 | 自动生成 | 进程实例标识,格式一般为 hostname-pid,便于日志区分 |
环境变量覆盖:
LM_WORKER_ID→ 覆盖worker_id(优先级最高)LM_INSTANCE_ID→ 覆盖instance_id
常见场景:
- 单机部署:
worker_id可不填,自动分配即可。 - 多实例同机/多机:每台实例配置不同的
worker_id,否则可能产生重复 ID。
database — MySQL 数据库
| 字段 | 默认值 | 说明 |
|---|---|---|
host | 空 | 数据库主机 |
port | 3306 | 端口 |
username | 空 | 用户名 |
password | 空 | 密码(建议用 LM_DATABASE_PASSWORD 环境变量) |
db_name | 空 | 数据库名 |
charset | utf8mb4 | 字符集,支持 emoji 必须用 utf8mb4 |
parse_time | true | 是否把 MySQL 时间解析为 Go 的 time.Time |
loc | Local | 时区,常用 Local 或 Asia/Shanghai |
max_idle_conns | 10 | 连接池最大空闲连接数 |
max_open_conns | 50 | 连接池最大打开连接数,按 QPS 与 MySQL max_connections 调整 |
conn_max_lifetime_minutes | 60 | 单连接最长存活时间(分钟),应小于 MySQL wait_timeout |
conn_max_idle_time_minutes | 10 | 空闲连接最长存活时间,避免拿到已断开的连接 |
skip_auto_migrate | false | true = 启动时不跑 GORM AutoMigrate;生产建议 true,改走 SQL 迁移 |
run_sql_migrations_on_startup | true | 启动时执行内嵌 SQL 迁移脚本 |
database.read_replica — 读写分离
| 字段 | 说明 |
|---|---|
enabled | 是否把 SELECT 路由到读库;写操作和事务仍走主库 |
host / port | 读库地址;留空则与主库相同(单机开发) |
dsn | 完整读库 DSN,设置后覆盖 host/port 拼接 |
max_idle_conns 等 | 读库连接池参数;0 表示沿用主库配置 |
database.shard — 水平分表
| 字段 | 说明 |
|---|---|
enabled | 是否启用分表;开启后 messages 按 conversation_id、notifications 按 user_id 分桶 |
message_buckets | 消息表分桶数,默认 512 |
notification_buckets | 通知表分桶数,默认 512 |
database.multidb — 垂直拆库
| 字段 | 说明 |
|---|---|
enabled | 是否把日志、归档、资金等表路由到独立数据库 |
log_db_name | 日志库名,如 lingmeng_log(存放 message_delivery_traces、各类 outbox 日志等) |
archive_db_name | 归档库名 |
fund_db_name | 资金库名 |
fund_writes_on_primary | 资金相关写操作是否仍留主库(需与余额同事务时为 true) |
database.topology — 拓扑切换
| 字段 | 说明 |
|---|---|
auto_backfill | 启用 shard/multidb 后是否自动回填历史数据 |
purge_source_after_backfill | 回填完成后是否删除源表数据 |
partition_auto_apply | 是否自动应用分区维护 |
环境变量: LM_DATABASE_HOST、LM_DATABASE_PORT、LM_DATABASE_USERNAME、LM_DATABASE_PASSWORD、LM_DATABASE_NAME
redis — 缓存与队列
| 字段 | 默认值 | 说明 |
|---|---|---|
host | 空 | Redis 主机 |
port | 6379 | 端口 |
password | 空 | 密码 |
db | 0 | 逻辑库编号 |
pool_size | 50 | 连接池大小 |
min_idle_conns | 10 | 最小空闲连接,减少突发时建连延迟 |
Redis 用于:接口缓存、限流计数、分布式锁、Asynq 消息队列、WebSocket 在线状态等。几乎所有生产部署都必须配置 Redis。
环境变量: LM_REDIS_HOST、LM_REDIS_PORT、LM_REDIS_PASSWORD、LM_REDIS_DB
cache — 缓存前缀
| 字段 | 说明 |
|---|---|
prefix | 所有 Redis Key 的统一前缀,默认 lingmeng。多套环境共用同一 Redis 时必须改成不同前缀 |
del_prefix_physical_scan | 版本号变更时是否 SCAN 物理删除旧 Key;默认 false(靠 TTL 自然过期)。内存紧张且无 TTL 时可开 true |
log — 日志
| 字段 | 默认值 | 说明 |
|---|---|---|
base_dir | static/logs | 日志根目录,按日期分子目录 YYYY-MM-DD/ |
console | true | 是否同时输出到控制台;生产建议 false,由日志采集器读文件 |
json | true | 是否 JSON 格式,便于 ELK / Loki 检索 |
slow_threshold_ms | 3000 | 慢请求阈值(毫秒),超过写入 slow.log |
access_async | true | 访问日志是否异步写,降低请求延迟 |
access_queue_size | 4096 | 异步访问日志队列长度 |
max_size_mb | 100 | 单文件最大体积,超过后轮转 |
max_backups | 10 | 每天每类日志最多保留几个备份文件 |
audit_body_max_bytes | 65536 | 审计日志记录请求体的上限,超过只记「已跳过」 |
server — HTTP 服务
| 字段 | 默认值 | 说明 |
|---|---|---|
read_timeout_seconds | 15 | 读取完整请求的最长等待时间 |
read_header_timeout_seconds | 5 | 读取请求头的超时,应小于 read_timeout_seconds |
write_timeout_seconds | 60 | 写出响应的最长等待;有大文件上传/下载时可适当加大 |
idle_timeout_seconds | 120 | Keep-Alive 空闲连接保留时间 |
max_header_bytes | 1048576 | 请求头最大 1MB |
api_prefix | /api | 所有业务 API 的统一前缀。改成 /backend-api 后,健康检查变为 GET /backend-api/ping。不影响 /ws 等独立路由 |
shutdown_timeout_seconds | 0 | 优雅关闭等待秒数;0 = 使用 write_timeout + 30 |
brotli_enabled | false | Gin 层 Brotli 压缩;生产通常由 Nginx/CDN 压缩,保持 false 即可 |
brotli_quality | 4 | 压缩质量 1~11 |
brotli_min_length | 4096 | 小于该字节数的响应不压缩 |
max_request_body_bytes | 4194304 | JSON 请求体上限 4MB;multipart 上传走 upload 段 |
使用 CDN 或反向代理时
若限流、登录日志里的客户端 IP 全部变成 CDN 出口 IP,请联系技术支持协助调整可信代理网段配置。
websocket — 实时连接
| 字段 | 默认值 | 说明 |
|---|---|---|
max_global_connections | 20000 | 单进程 WebSocket 连接上限,防止文件描述符耗尽 |
max_connections_per_user | 5 | 单用户最多几个并发连接(手机+电脑等),超出踢最旧的 |
presence_redis_timeout_ms | 800 | 在线状态写 Redis 的超时,应远小于 Redis 读超时 |
startup — 启动模式
| 字段 | 说明 |
|---|---|
strict_dependencies | 严格依赖检查;app.env=prod 时框架会强制开启,核心依赖连不上直接退出 |
mode | 启动模式,见下表 |
worker_health_port | worker 模式下的健康检查端口,默认 9090 |
generate_swagger_on_start | 启动时是否重新生成 Swagger;生产务必 false |
mode 值 | 含义 |
|---|---|
full | 完整模式:HTTP + 定时任务 + 队列消费者(默认) |
http_only | 只提供 HTTP API,不跑定时任务和队列 |
worker | 只跑后台任务,不监听 HTTP |
admin_only | 预留的管理端独立部署,当前与 http_only 相同 |
环境变量: LM_STARTUP_MODE(优先级高于配置文件)
多实例部署示例:
- API 实例 × N:
mode: http_only或full,task.enabled: false(若不想重复跑定时任务) - Worker 实例 × 1:
mode: worker,专门跑定时任务和队列
cors — 跨域
| 字段 | 说明 |
|---|---|
allowed_origins | 允许的前端域名列表;生产禁止 *,应写具体域名如 https://admin.example.com |
allowed_headers | 允许的请求头 |
allowed_methods | 允许的 HTTP 方法 |
allow_credentials | 是否允许携带 Cookie;与 allowed_origins: "*" 通常不兼容 |
max_age_seconds | 浏览器缓存预检 OPTIONS 结果的秒数 |
queue — 异步消息队列
基于 Redis 的 Asynq 队列,处理发通知、刷新缓存、导出等耗时操作。
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled | true | 队列消费者总开关;关闭后异步任务只入队不消费 |
concurrency | 10 | 同时处理多少个任务;按 CPU 和 Redis 性能调整,不宜过大 |
upload — 上传限制
| 字段 | 说明 |
|---|---|
max_multipart_memory_mb | 表单解析在内存中保留的上限,超出部分写临时文件 |
max_file_size_mb | 单文件大小兜底上限(后台「功能与上传」可覆盖) |
media_command_timeout_seconds | ffmpeg/ffprobe 等媒体命令最长执行时间 |
meilisearch — 全文搜索
| 字段 | 说明 |
|---|---|
enabled | 是否启用;false 时搜索降级为 MySQL FULLTEXT |
host | 服务地址,如 http://127.0.0.1:7700 |
api_key | API 密钥 |
timeout_seconds | 请求超时 |
degrade_seconds | 连续失败后的降级窗口,窗口内直接走 MySQL |
gorse — 推荐引擎
| 字段 | 说明 |
|---|---|
enabled | 是否启用 Gorse 协同过滤推荐 |
base_url | Gorse API 地址 |
api_key | API 密钥 |
timeout_seconds / read_timeout_ms | 请求超时 |
degrade_seconds | 失败降级窗口 |
readiness_cache_seconds | 就绪状态缓存秒数 |
item_to_item_recommender | 物品相似推荐算法名 |
user_to_user_recommender | 用户相似推荐算法名 |
non_personalized_recommender | 非个性化推荐(如热门)算法名 |
nebula — 图数据库
用于「共同好友」等社交图查询。
| 字段 | 说明 |
|---|---|
enabled | 是否启用 |
host / port | 服务地址,默认 9669 |
username / password | 登录账号 |
space | 图空间名称 |
timeout_seconds | 连接超时 |
rate_limit — 全局限流
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled | true | 全站 API 限流开关 |
scene | api | 限流场景标识,用于 Redis Key 拼接 |
window_seconds | 60 | 统计窗口(秒) |
limit | 300 | 窗口内同一标识最多请求次数 |
identifier | ip | 限流维度,当前支持 ip |
rate_limit_scenes — 场景化限流
在全局限流之上叠加更细的策略。每个场景结构相同:
| 子字段 | 说明 |
|---|---|
enabled | 是否启用该场景 |
window_seconds | 统计窗口 |
limit | 窗口内最大次数 |
identifier | ip / user_id / bearer(MCP Token) |
| 场景名 | 保护什么 |
|---|---|
login | 密码登录防爆破 |
captcha | 验证码获取 |
register | 注册 |
otp | 短信/邮箱验证码发送 |
password_reset | 找回密码 |
ai / ai_generate / ai_async_job | AI 接口 |
payment / payment_create | 支付 |
withdraw_apply | 提现申请 |
ws_ticket / ws_connect | WebSocket |
mcp_call | MCP 工具调用 |
admin_dangerous | 后台高危操作 |
write | 发笔记、评论、点赞等写操作 |
open_stream_events / open_stream_notes | 对外开放的内容流 API |
ip2region — 离线 IP 归属地
当后台「阿里云 → IP 归属地接口」选 ip2region 时使用。
| 字段 | 说明 |
|---|---|
v4_xdb_path | IPv4 离线库路径 |
v6_xdb_path | IPv6 离线库路径 |
searcher_pool_size | 查询器连接池大小 |
task — 定时任务
这是运维最常改的配置块之一。
顶层字段
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled | true | 定时任务总开关;多实例时通常只在一台实例开启 |
run_on_start | false | 启动后是否立即跑一遍所有任务(不等第一个周期) |
log_retain_days | 7 | 日志目录保留天数;0 = 永不清理 |
data_retention | 见下表 | 数据库表数据保留天数 |
default | — | 所有任务的默认治理策略 |
jobs | — | 按任务名覆盖单个任务的参数 |
task.data_retention — 数据保留天数
由 system.data_retention_cleanup、notification.cleanup、system.activity_cleanup 等任务使用。设为 0 表示不清理对应数据。
| 字段 | 默认 | 清理什么 |
|---|---|---|
message_delivery_traces_days | 30 | 消息推送链路追踪(排障日志,数据量大) |
notification_read_days | 90 | 已读站内通知 |
activity_days | 90 | 系统动态(system_activities) |
business_event_outbox_terminal_days | 30 | 已成功/已忽略的业务事件 outbox |
business_event_outbox_dead_days | 90 | 已死亡的 dead 状态 outbox |
notify_outbox_sent_days | 14 | 已发送的通知 outbox |
task_event_outbox_success_days | 7 | 已成功的用户任务 outbox |
recommend_events_days | 90 | 推荐埋点事件 |
note_popularity_logs_days | 90 | 笔记热度计算流水 |
ai_call_logs_days | 180 | AI 调用日志 |
mcp_call_logs_days | 180 | MCP 调用日志 |
user_login_logs_days | 365 | 用户登录日志 |
user_security_logs_days | 365 | 用户安全日志(改密、绑定等) |
磁盘占用大时怎么调?
若 message_delivery_traces 或 notifications 表过大,可优先缩短 message_delivery_traces_days(如 7)和 notification_read_days(如 30),重启后等待清理任务执行(默认每 6 小时)。
task.default — 任务默认策略
| 字段 | 默认值 | 说明 |
|---|---|---|
timeout_seconds | 600 | 单次任务最长执行时间(秒),超时会被取消 |
lock_enabled | true | 多实例时是否用 Redis 分布式锁,避免重复执行 |
lock_ttl_seconds | 0 | 锁 TTL;0 = 按超时或执行周期自动推导 |
task.jobs — 单任务配置
在 jobs 下用任务名作为 Key。常用可配字段:
| 字段 | 说明 |
|---|---|
enabled | 是否启用该任务 |
interval_seconds | 执行间隔(秒) |
timeout_seconds | 单次超时 |
lock_enabled | 是否加分布式锁 |
run_on_start | 启动时是否立即执行一次 |
batch_size | 每批处理条数(分批任务) |
max_items_per_run | 单轮最多处理条数,0 = 任务内置预算 |
主要定时任务一览:
| 任务名 | 默认间隔 | 做什么 |
|---|---|---|
system.log_cleanup | 1 小时 | 清理过期日志目录 |
system.tmp_cleanup | 30 分钟 | 清理 static/tmp 临时文件 |
system.data_retention_cleanup | 6 小时 | 按 data_retention 清理各类日志表 |
system.health_check | 5 分钟 | 巡检 outbox 积压、队列深度、连接池、内存 |
system.activity_cleanup | 1 天 | 清理过期系统动态 |
notification.cleanup | 6 小时 | 清理过期已读通知 |
event.business_event_outbox | 5 秒 | 消费业务事件 outbox |
user.task_event_outbox | 30 秒 | 消费用户任务 outbox |
lottery.auto_draw | 1 分钟 | 抽奖到期自动开奖 |
note.hot_refresh | 1 小时 | 刷新笔记热度 |
recommend.gorse_sync | 30 分钟 | 同步数据到 Gorse |
message.archive | 1 天 | 私信冷归档 |
order.reconcile | 10 分钟 | 订单资金对账 |
fund.reconcile | 10 分钟 | 资金流水对账 |
search.rebuild | 30 天 | 搜索索引全量重建(运维兜底) |
system.health_check 还可单独配置告警阈值:outbox_business_warn、queue_depth_warn、db_pool_saturation_ratio 等。
forbidden_word — 违禁词(种子配置)
| 字段 | 说明 |
|---|---|
enabled | 是否开启违禁词检测 |
default_action | reject 拒绝 / mask 掩码 / log_only 仅记录 |
mask_char | 掩码替换字符 |
min_word_len | 词表加载时忽略短于此长度的词 |
INFO
运行期策略以数据库 forbidden_word_settings 为准;此处只是首次种子。日常维护请用 全局违禁词 后台页面。
captcha — 验证码
| 字段 | 说明 |
|---|---|
master_code | 万能验证码;生产环境必须留空。仅本地开发可在自建 config.yaml 中设置 |
login_lockout — 登录防爆破
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled | true | 是否启用 |
max_attempts | 5 | 窗口内最多失败几次 |
lockout_seconds | 900 | 锁定多久(秒),默认 15 分钟 |
window_seconds | 900 | 失败计数窗口 |
jwt — 登录令牌
| 字段 | 说明 |
|---|---|
secret | JWT 签名密钥,生产必须强随机;用 LM_JWT_SECRET 环境变量覆盖 |
expire_hours | Token 有效期(小时),默认 72 |
security — 敏感数据加密
| 字段 | 说明 |
|---|---|
secret_key | AES-GCM 加密密钥(微信 Token、AI API Key 等);LINGMENG_SECRET_KEY 或向导配置 |
file_signature_secret | 私有文件短期访问链接的 HMAC 密钥;LM_FILE_SIGNATURE_SECRET |
admin_security — 管理后台安全
| 字段 | 说明 |
|---|---|
ip_whitelist_enabled | 是否只允许白名单 IP 访问后台 |
allowed_ips | 白名单 IP 列表;超级管理员不受限 |
max_concurrent_sessions | 每管理员最多几个并发会话;0 = 不限制 |
tracing — 分布式追踪
| 字段 | 说明 |
|---|---|
enabled | 是否启用 OpenTelemetry;app.env=local 时未配置则默认开启 |
service_name | 服务名,留空用 app.name |
otlp_endpoint | OTLP 采集端地址,如 localhost:4318 |
otlp_insecure | 是否明文 HTTP |
sample_ratio | 采样率 0~1;生产高流量可降到 0.1~0.3 |
health_center — 服务健康中心
自动探活、渐进式自愈、必要时触发进程重启(需配置 process_manager)。
| 字段 | 说明 |
|---|---|
enabled | 总开关 |
interval_seconds | 探活间隔,默认 10 秒 |
recovery_window_seconds | 恢复观察窗口 |
heal.max_attempts | 自愈最大尝试次数 |
heal.attempt_interval_seconds | 自愈重试间隔 |
restart.enabled | 是否允许自动重启 |
restart.cooldown_seconds | 两次重启之间的冷却时间 |
restart.process_manager | systemd / docker / k8s 等 |
mysql.* / redis.* / api.* | 各维度故障判定阈值 |
reconcile — 对账告警
| 字段 | 说明 |
|---|---|
alert_critical_enabled | critical 级差异是否写入系统动态 + Prometheus |
auto_fix_enabled | 对账任务是否自动修复可修复项 |
auto_fix_max_per_run | 每轮最多自动修复条数 |
feature_flags — 特性开关
YAML 提供默认值,可在数据库中动态覆盖。
| 字段 | 说明 |
|---|---|
enabled | 是否启用特性开关系统 |
cache_ttl_seconds | 开关值缓存秒数 |
defaults.* | 各功能默认开/关,如 store、membership、ai.multimodal 等 |
prometheus — 指标暴露
| 字段 | 说明 |
|---|---|
enabled | 是否暴露 /metrics;local 环境默认开启 |
path | 指标路径,默认 /metrics(不受 api_prefix 影响) |
namespace | 指标名前缀,如 lingmeng_http_requests_total |
recommend — 推荐系统
总开关 enabled;下设多个子模块,常用项:
| 子块 | 作用 |
|---|---|
feed | 信息流推荐条数、Gorse 召回倍数、热门兜底 |
user_recommend | 「聊得来的人」:共同好友 + 兴趣相似 + 浏览标签 |
related | 笔记相关推荐:文本/话题/圈子/ItemCF 权重与缓存 |
embedding | 向量召回:模型、维度、相似度阈值 |
itemcf | 物品协同过滤离线权重 |
ltr | 学习排序:样本天数、训练轮数、标签权重 |
rerank | 重排:MMR 多样性、同作者/同话题上限 |
ab | A/B 实验默认变体与流量比例 |
metrics | 推荐效果基线采样 |
gorse_sync | 同步到 Gorse 的批量大小 |
具体数值含义见各字段旁注释;调优前建议先在测试环境观察 CTR 与延迟。
llmchat — AI 对话
| 字段 | 说明 |
|---|---|
stream_timeout_seconds | 流式 SSE 超时,应小于 server.write_timeout_seconds |
storage — 本地文件存储
| 字段 | 说明 |
|---|---|
base_dir | 上传文件保存目录 |
public_prefix | 对外 URL 前缀 |
x_accel_redirect_prefix | Nginx 内部静态路径;配置后由 Nginx 直接发文件,减轻 Go 压力 |
云存储(COS/OSS/七牛)在管理后台 → 系统配置 → 文件存储配置,不在 config.yaml。
环境变量速查
部署时建议密钥全部用环境变量,避免明文写入磁盘:
| 环境变量 | 对应配置 |
|---|---|
LM_DATABASE_HOST | database.host |
LM_DATABASE_PORT | database.port |
LM_DATABASE_USERNAME | database.username |
LM_DATABASE_PASSWORD | database.password |
LM_DATABASE_NAME | database.db_name |
LM_REDIS_HOST | redis.host |
LM_REDIS_PORT | redis.port |
LM_REDIS_PASSWORD | redis.password |
LM_REDIS_DB | redis.db |
LM_JWT_SECRET | jwt.secret |
LM_FILE_SIGNATURE_SECRET | security.file_signature_secret |
LM_STARTUP_MODE | startup.mode |
LM_WORKER_ID | app.worker_id |
LM_INSTANCE_ID | app.instance_id |
常见问题
改了 config.yaml 没生效?
必须重启进程。可对照日志里启动时打印的配置项确认是否加载。
多实例部署定时任务跑重复了?
确保只有一台实例 task.enabled: true,或依赖 lock_enabled: true(默认开启)的 Redis 分布式锁。
数据库表越来越大怎么办?
优先调整 task.data_retention,尤其是 message_delivery_traces_days 和 notification_read_days。详见上文 数据保留天数。
