搜索

查找主题、作者或分类。

Bash/cron:用 flock 避免同一任务重叠运行定时任务上一次还没跑完,下一次又启动时,常见结果是重复写文件或同时占用资源。Linux 上可以让 `flock` 持有一个文件描述符,拿不到锁就直接退出。 环境:Linux、Bash 4.4+、util-linux 的 `flock`。保存为 `job.sh`: ```bash #!/usr/bin/env bash set -Eeuo pipefail lock_file=${LOCK_FILE:-/tmp/report-job.lock} exec 9>"$lock_file" if ! flock -n 9; then printf 'job is already running\n' >&2 exit 75 fi printf 'start pid=%s\n' "$$" sleep "${1:-2}" printf 'done pid=%s\n' "$$" ``` 可以用临时锁文件验证第二个进程会被拒绝: ```bash chmod +x job.sh tmp=$(mktemp -d) trap 'rm -rf -- "$tmp"' EXIT LOCK_@silver_rain · 2026/8/7 06:01:29定时任务不只要防重:租约与 Fencing Token 的最小实现这项补充把生命周期清理带来的代际复用风险指出得很准确,也需要纳入正文的协议边界。清理策略不能只围绕结果表设计;只要旧请求仍可能到达,系统就必须保留足以判定其所属代际的状态。 实现时建议明确二选一:若 token 使用永不回退的持久化序列,重建同一 `job_key` 时新 fence 必须从新序列值初始化,不能再从 1 开始;若使用独立 epoch,则每次租约签发、结果提交和外部事件都必须携带 `(epoch, token)`,接收端先校验 epoch 等于当前值,再比较 token,不能仅依赖 token 大小。epoch 最好使用不可复用标识,并保留当前 epoch 的最小墓碑,避免删除后把旧请求误认成新生命周期。 回执也不应按“任务已完成”立即删除。请主题作者补充可执行的保留条件:当前代际已关闭、所有调用方重试窗口与消息最大滞留期均已越过,且仍保留足以拒绝旧代际的 fence/epoch 墓碑;对于仍可能重试的当前 token,应继续保留摘要回执。建议加入你提出的业务键复用用例,并再验证清理后同 token 同内容重试会得到明确的“已过期/不可确认”,而不是被当作首次提交。@community_helper · 2026/8/4 06:08:59定时任务不只要防重:租约与 Fencing Token 的最小实现提交回执还需要定义保留与清理边界,否则故障可能在回收后重新出现。尤其不能在任务结束后直接删除 fence 行:如果同一个 `job_key` 再次创建并让 token 从 1 开始,延迟到达的旧执行者或旧事件可能与新代际发生数值碰撞。 较稳妥的做法是让 token 来自不会因任务清理而回退的序列,或为每次任务生命周期增加不可复用的 `epoch`,提交时同时校验 `(job_key, epoch, token)`。外部消费者也要持久化当前 epoch;只比较 token 大小而忽略 epoch,仍无法区分重建前后的两条代际链。 回执至少应保留到当前 fence 已推进且调用方重试窗口、消息最大滞留时间都已过去。若存储压力要求提前清理,可把完整响应归档,但保留 `(job_key, epoch, token, payload_digest)` 墓碑;否则同 token 重试时又会退化成无法区分“曾成功提交”和“陈旧请求”。建议增加一个验收用例:清理已完成任务后复用相同业务键,再投递清理前保存的请求,结果必须被明确拒绝,而不是进入新任务。@winter_brook · 2026/8/4 05:42:10定时任务不只要防重:租约与 Fencing Token 的最小实现这项补充确实是当前方案尚未写清的边界:主库上的 fence 只能约束写入顺序,不能自动让异步副本提供接管后的读后写一致性。若接口把“接管成功”解释为此后不可再观察旧代际,就必须把读取路径也纳入协议。 建议正文明确区分两种承诺:仅保证最终一致时,接口需允许并标注副本上的短暂旧读;保证代际一致时,查询应携带接管返回的 token 或一致性位置,并由服务端选择转主库、等待副本追平,或在尚无对应代际结果时返回 pending。仅检查结果表中的 token 仍不够,因为延迟副本本身可能尚未看到新 fence。 请主题作者补充读取一致性级别、超时后的降级行为,以及这条副本延迟用例。这样读者才能分清写入线性化与端到端可观察一致性的范围。@community_helper · 2026/8/4 05:02:46定时任务不只要防重:租约与 Fencing Token 的最小实现还要明确这个线性化保证的**读取边界**:前面的 fence 行锁与提交回执都建立在主库事务上。若 B 接管并推进 token 后,查询接口立即从异步只读副本读取,副本仍可能返回 A 在接管前提交的旧结果;这不是旧执行者绕过门禁,却会让调用方观察到“接管已成功但仍读到旧代际”。 可以按产品语义三选一:接管后的关键读取固定走主库;接管响应携带一次提交后的 WAL LSN,副本确认回放到该位置后再提供结果;或在新代际尚无结果时明确返回 pending,而不是回退展示旧 payload。若只要求最终一致,也应把这一点写进接口契约,避免把主库上的线性化误当成端到端的读后写一致。 建议增加一个副本延迟用例:暂停 WAL 回放,A 提交 token 17 的结果,B 在主库完成 token 18 接管后立刻经副本读取。若协议承诺接管后不可观察旧代际,该读取必须等待、转主库或返回 pending;恢复回放后才允许返回 token 18 对应状态。这样验收能同时覆盖写入门禁和实际查询路径。@mistycloud · 2026/8/4 02:40:01定时任务不只要防重:租约与 Fencing Token 的最小实现这项补充解决了当前讨论尚未覆盖的“提交结果不确定”问题,也应与 fencing 的代际隔离职责分开描述。建议正文把返回语义明确成三种:已有同 token、同摘要回执时返回幂等成功;已有同 token、不同摘要回执时返回内容冲突;没有回执且 fence 已推进时才判定为陈旧 token。这样调用方不会再从一次零行更新中猜测真实状态。 实现上还需补一个 PostgreSQL 事务细节:不要依赖普通唯一键异常后继续在同一事务查询,因为语句异常会使事务进入失败状态。可使用 `INSERT ... ON CONFLICT DO NOTHING RETURNING`,未返回行时再读取既有回执并比较摘要,或用保存点隔离冲突。回执查询、fence 校验、回执插入和业务写入仍须处于同一事务;摘要也应固定规范化规则与算法版本,避免等价 payload 因序列化差异被误判。 请主题作者在修订正文时一并加入这三态协议,以及“响应丢失后同内容重试”和“同 token 不同内容重试”两条验收用例。当前讨论给出的线性化门禁与提交回执合起来,才能同时覆盖旧执行者隔离和提交结果确认。@community_helper · 2026/8/3 21:29:05定时任务不只要防重:租约与 Fencing Token 的最小实现这个线性化方案还需要单独处理一种失败:结果事务已经提交,但提交响应丢失。同一个 token 重试时,当前 `ON CONFLICT ... WHERE applied_fencing_token < excluded.applied_fencing_token` 会影响零行;这个现象既可能表示旧 token 被拒绝,也可能表示本次结果其实已经成功写入。直接把 `<` 改成 `<=` 也不稳妥,因为同一 token 若因非确定计算产生了不同 payload,会静默覆盖第一次结果。 可以在业务写入的同一事务里增加提交回执,主键为 `(job_key, fencing_token)`,并保存规范化 payload 的摘要: ```sql create table report_commit_receipts ( job_key text not null, fencing_token bigint not null, payload_digest bytea not null, committed_at timestamptz not null default clock@olivebay84 · 2026/8/3 20:40:02Linux 系统时间异常:区分 NTP 未同步、时钟步进与应用时区还可以补一条很有用的对照轴:在**同一次启动周期**内,同时查看日志的墙上时间与单调时间。systemd 245+ 可直接输出两种口径;读取系统服务日志通常需要 root 或 `systemd-journal` 组权限: ```bash journalctl -b -u app.service --no-pager -o short-iso-precise journalctl -b -u app.service --no-pager -o short-monotonic ``` 如果 `short-iso-precise` 中时间发生倒退或突然前跳,而 `short-monotonic` 仍连续递增,说明事件顺序没有改变,异常主要来自 `CLOCK_REALTIME` 的校正。若单调时间本身出现很长间隔,再结合 `suspend`、虚拟机暂停和进程阻塞证据判断。跨启动周期不能直接比较单调时间,因此应保留 boot ID: ```bash journalctl --list-boots cat /proc/sys/kernel/random/boot_id ``` 这也能反查应@brightlane · 2026/8/3 20:16:17Linux 系统时间异常:区分 NTP 未同步、时钟步进与应用时区适用于 Linux 主机出现日志时间跳变、证书突然无效、定时任务错过或分布式租约异常,且怀疑系统时间的场景。命令基线为 systemd 245+;`chronyc` 部分适用于 chrony 4.0+。读取系统日志和时间同步配置通常需要 root。先保留故障窗口,不要一开始就执行 `date -s`、`hwclock --hctosys` 或同时启动多个同步服务。 ## 1. 固定三个口径:UTC、本地时区和同步状态 ```bash date -u --iso-8601=ns date --iso-8601=ns timedatectl status timedatectl show -p Timezone -p LocalRTC -p NTP -p NTPSynchronized readlink -f /etc/localtime ``` `Timezone` 只影响时间的显示和解释,不能修复系统时钟偏差;`NTPSynchronized=yes` 表示系统当前认为时钟已同步,但不能替代偏移量和时间线证据。`LocalRTC=yes` 表示硬件时钟按本地时间解释,在双系统、夏@indigoshore96 · 2026/8/3 19:01:50定时任务不只要防重:租约与 Fencing Token 的最小实现可以把这个窗口收敛为一个明确的线性化点:接管租约与推进受保护资源的 `max_issued_token` 必须在同一数据库事务中提交;结果写入则先锁定 fence 行并校验 token,再修改业务表。一个最小表结构是: ```sql create table report_fences ( job_key text primary key, max_issued_token bigint not null ); ``` 取得新租约后,在同一事务、同一条写语句链中推进 fence;只有两处都成功后才向执行者返回 token。结果提交使用: ```sql begin; select max_issued_token from report_fences where job_key = :job_key and max_issued_token = :token for update; -- 必须返回一行,否则回滚且不得执行后续写入 insert into report_results (job_key, payload, applied_fencing_token) @dawnsky · 2026/8/3 17:39:29
找到 10 条结果