gpt4 book ai didi

linux - Linux 中类似 Oracle 的序列?

转载 作者:太空宇宙 更新时间:2023-11-04 10:47:11 25 4
gpt4 key购买 nike

我需要在单个公共(public)日志文件(一天数千次调用)中用唯一编号标记对我的程序的并行调用。

为此,Oracle 序列将是完美的(返回的数字保证唯一性)。我可以使用系统文件锁定设施用一个小的 C 程序(C 代表速度,这就是这里的问题)来实现它,但是 Linux 是否已经提供了这样的设施(/dev/increment_forever 会很好 :)),或者有人出局了已经有这样的实用程序了吗?

编辑:忘记提及我的程序不是持久进程(它不是服务器),所以 100 次调用 == 我的程序的 100 个实例。使用 FS 文件存储计数器会太慢,需要锁定机制。这就是为什么像/dev/increment_forever(别名:系统设施)这样的东西是完美的。

最佳答案

首先:您严重高估了 Linux 上建议锁定的成本。与您已经为启动程序的唯一实例支付的价格相比,使用 flock 在更新具有唯一标识符的文件之前获得独占锁是便宜的。 (当然,进行基于重命名的原子更新——更新文件而不是持有锁的文件——会在文件系统元数据变动和日志记录方面产生一些额外成本,但对于每天数千次调用来说,这不算什么;一个人会如果您需要每秒生成数千个标识符,请担心)。

第二:你的问题暗示你真正需要的是唯一性,而不是排序。这使您处于一个根本不需要协调或锁定的空间。考虑 type-1 UUID 采用的方法(使用非常高精度的时间戳,可能与其他信息结合——考虑 CPU 标识符,因为在给定时间只有一个进程可以在一个 CPU 上;或 PID,因为只有一个进程在给定时间可以有一个 PID),或者由 type-4 UUID(使用纯随机值)获取。结合您的进程的 PID 和它开始的时间戳(后者是 /proc/self/stat 的第 22 列),您应该被设置。


这比直接使用 flock 调用的 native C 实现要慢得多,但应该让您了解正确的实现:

retrieve_and_increment() {
local lock_fd curr_value next_value

# using a separate lockfile to allow atomic replacement of content file
exec {lock_fd}<>counter.lock
flock -x "$lock_fd" || {
exec {lock_fd}<&-
return 1
}
next_value=$(( $(<counter) + 1 ))
printf '%s\n' "$next_value" >counter.next && mv counter.next counter
exec {lock_fd}<&- # close our handle on the lock

# then, when not holding the lock, write result to stdout
# ...that way we decrease the time spent holding the lock if stdout blocks
printf '%s\n' "$next_value"
}

请注意,我们正在为 mv 启动一个外部命令,因此 flock 并不是我们在这里支付 fork/exec 成本的唯一时间 -- a为什么这会在您的 C 程序中更好地实现。


对于真正需要每秒生成数千个唯一序列值的阅读本文的其他人,我强烈建议使用 Redis用于此目的的数据库。 The INCR command将在 O(1) 时间内自动增加与键关联的值并返回该值。如果认为建立到本地服务的 TCP 连接太慢/太昂贵,Redis 还支持通过 Unix 套接字进行连接。

在我不是特别结实的笔记本电脑上:

$ redis-benchmark -t INCR -n 100000 -q
INCR: 95510.98 requests per second

每秒 95,000 个请求可能已经足够了。 :)

关于linux - Linux 中类似 Oracle 的序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32656671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com