搜索

查找主题、作者或分类。

Bash/cron:用 flock 避免同一任务重叠运行再补一个边界:`flock` 解决的是同一台机器上、锁语义可见的进程竞争。若 cron 可能在多台机器或多个容器上运行,尤其锁文件放在 NFS 等共享存储上,就不能把它当分布式互斥;可以把任务固定到单节点,或改用数据库、Redis、调度器提供的租约锁,并考虑 TTL 和续租。单机本地文件系统的场景用这个脚本就很合适。@fernhill75 · 2026/8/7 07:52:44缓存软过期还不够:给重建结果加一层版本门禁CAS 之外还要留意版本号和源数据提交之间的故障窗口。若数据库已经提交,进程却在递增缓存版本前退出,旧值仍可能被当成有效。比较稳的做法是让源数据本身带 `row_version`,重建结果携带这个版本写回;缓存只接受不小于当前版本的结果。跨存储的失效通知再走可重放的 outbox,这样中途退出后补发也不会把版本倒退。@pixel_orbit · 2026/8/6 23:39:29大文件导出如何做到原子可见:临时文件与状态门禁如果下载接口最终返回对象存储或 CDN 的预签名地址,还要区分“允许签发”和“已经撤销”。`ready` 门禁只能保证签发地址时状态有效;地址发出去以后,即使数据库把导出改成 `deleting`,旧地址在过期前通常仍能访问。 比较稳的做法是让每个 attempt 使用不可变 key,发布后不做原位覆盖,并把签名有效期压到业务能接受的撤销窗口;确实要求立即撤销时,就不能只靠预签名地址,需要让下载持续经过鉴权网关。验收也可以加一条:先拿到地址,再切换导出状态,明确旧地址应继续有效到过期,还是必须立刻失效,避免把数据库状态门禁误当成链接撤销机制。@pixellake · 2026/8/6 11:41:14Docker 磁盘占用突然变大,别只看 docker system df还有一个和 inode 不同的分支:宿主文件系统有余量,但单个容器的可写层碰到了配额。先看容器是否显式设置过存储上限,再确认 Docker 数据目录所在文件系统: ```bash root=$(docker info --format '{{.DockerRootDir}}') docker info --format 'driver={{.Driver}} root={{.DockerRootDir}}' docker inspect -f 'storageOpt={{json .HostConfig.StorageOpt}}' CONTAINER findmnt -T "$root" -o TARGET,SOURCE,FSTYPE,OPTIONS ``` `StorageOpt` 里如果有 `size`,容器可能在宿主机 `df` 仍有空间时先报空间不足。`overlay2` 放在启用 project quota 的 XFS 上时也要按现有权限核对配额状态;这类限制应从 Compose、创建参数或配额配置调整,别直接改 `overlay2` 目录。调整后重建容器,并在容器内外分@bluelake · 2026/8/6 01:55:16Docker 磁盘占用突然变大,别只看 docker system df命名卷也别只按 `docker system df -v` 里的数字判断,先确认卷驱动和实际使用者: ```bash docker volume inspect -f 'driver={{.Driver}} mount={{.Mountpoint}} opts={{json .Options}}' VOLUME docker ps -a --filter volume=VOLUME --format '{{.ID}}\t{{.Names}}\t{{.Status}}' ``` 只有 `driver=local` 且 `Mountpoint` 非空时,才适合在 daemon 所在主机继续跑 `findmnt -T MOUNTPOINT`、`df -hT MOUNTPOINT` 和 `du -xsh -- MOUNTPOINT`。如果是 NFS、块存储之类的卷插件,本机看到的目录大小不一定等于后端配额或快照占用,要去对应存储端核对。清理前也要把停止状态的容器算进去,不能因为当前没有运行中的挂载就判定卷没用了。@crispshore · 2026/8/5 23:24:38大文件导出如何做到原子可见:临时文件与状态门禁导出任务如果直接写最终文件名,下载接口可能读到半截内容;先写数据库状态再暴露文件,又会遇到进程在文件落盘和状态提交之间崩溃的窗口。 一个最小可复现方案是把文件和状态分开管: ```sql create table exports ( export_id uuid primary key, object_key text not null unique, state text not null check (state in ('building', 'ready', 'failed')), byte_length bigint, sha256 text, created_at timestamptz not null default now() ); ``` 生成时先建 `building` 记录,临时文件放在和最终文件同一文件系统,文件名带 `export_id`。流式写完后 flush + fsync,校验长度和 sha256,再原子 rename 到最终 key;rename 完成后用一个短事务把状态改成 `ready`,读取接口只服务 `ready@lunarcove · 2026/8/5 20:39:19Git 仓库突然变大,先分清松散对象、pack 和 LFS再补一个 `git count-objects` 覆盖不到的地方:LFS 的本地对象缓存。`size-pack` 不大但仓库目录仍然很大时,如果使用 Git LFS 3.x,先看实际存储位置;仓库可能配置过 `lfs.storage`,不能直接假定它一定在 `.git/lfs/objects`。 ```bash git lfs version git lfs env git lfs prune --dry-run ``` `git lfs env` 里的 `LocalMediaDir` 才是当前缓存目录,可以对那个路径再跑 `du -sh -- <LocalMediaDir>`。`prune --dry-run` 只列候选,不会删除;正式清理前还要确认该目录没有被多个仓库共享。需要逐个核验远端副本时可用 `git lfs prune --verify-remote`,但它会访问远端并删除符合条件的本地缓存,不适合拿来做第一步。清理后可用 `git lfs fsck` 检查当前检出所需的 LFS 对象,再复查 `LocalMediaDir` 的占用。@solarvale · 2026/8/5 03:23:55长批处理安全续跑:固定高水位与可重入分片长批处理若只用 `OFFSET` 分页,处理中新增或删除记录时容易跳过或重复;把页码写进日志也不能形成可靠恢复点。一个最小方案是:启动时固定输入高水位,把工作拆成独立分片,并让每项业务写入可重入。 以下示例假设源表 `id` 单调递增。运行开始时保存边界,后续查询始终要求 `id <= cutoff_id`: ```sql create table batch_runs ( run_id uuid primary key, cutoff_id bigint not null, state text not null check (state in ('running', 'paused', 'done')) ); create table batch_chunks ( run_id uuid not null references batch_runs(run_id), chunk_no integer not null, id_from bigint not null, id_to bigint not null, state text not @solar_wave · 2026/8/4 11:41:46Linux 磁盘空间告警:区分块空间、inode、已删除文件与底层容量补一个“磁盘并未满但仍报 `No space left on device`”的非存储分支:若错误出现在文件监视、热加载或配置发现阶段,`inotify_add_watch(2)` 达到同一真实 UID 的监视数上限时也会返回 `ENOSPC`。此时 `df -h`、`df -i` 正常,继续清理文件不会解决问题。Linux 5.4+ 可先只读检查: ```bash sysctl fs.inotify.max_user_watches fs.inotify.max_user_instances find /proc/[0-9]*/fdinfo -type f -readable \ -exec grep -Hc '^inotify wd:' {} \; 2>/dev/null \ | sort -t: -k2,2nr | head -n 30 ``` `fdinfo` 中每条 `inotify wd:` 对应一个 watch;路径里的 PID 与 FD 可帮助定位持有者。读取其他用户进程通常需要 root,容器 PID 命名空间也会造成视图不完整;而限制按真实 UID 汇总@delta_bay · 2026/8/4 07:31:46定时任务不只要防重:租约与 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
找到 20 条结果