请问 Django 并发条件下,生成雪花 ID 为什么会重复?

2021-07-30 13:31:32 +08:00
 Phishion

我用的是别人写好的模块,如下

https://github.com/tarzanjw/pysnowflake/blob/master/snowflake/server/generator.py

我首先自己跑单线程测了一下,完全不会有重复,多线程在加线程锁的情况下也完全没有发生重复。

但是我在实际项目中生成的时候,大概 10 条线提交总共 1600 条数据,每次都会产生大概几十条重复

我打印过 ID,这个雪花生成器实例并没有被初始化多个,请问如何排查?

大致代码如下:

from newsnow import Generator
logger = logging.getLogger('django-production')
get_flake_id = Generator(dc=0, worker=0)

def create_product_meta(prepare_product_meta):
    new_product = models.productMeta(
        own_store=prepare_product_meta.get("own_store").upper(),
        product_name=prepare_product_meta.get("product_name"),
    )
    logger.warning(id(get_flake_id))
    new_product.flake_id = get_flake_id.get_next_id()
    return new_product
3793 次点击
所在节点    Python
26 条回复
todd7zhang
2021-07-30 15:44:36 +08:00
差不多啦,uwsgi 启动的子进程的 pid 基本都是连续递增的,这边还有 worker & 0xff, 一台机器支持 256 个 worker 呢。
实际启动的时候就那么几个进程,没那么巧就重复了吧,哈哈。
caviar
2021-07-30 23:53:03 +08:00
既然是用 uwsgi,直接拿 uwsgi 的 worker id 咯 https://uwsgi-docs.readthedocs.io/en/latest/API.html#uwsgi-worker-id
Phishion
2021-07-31 00:05:46 +08:00
@caviar 实际上 os.getpid() 打印的就是 uwsgi 的 PID,通过观察我发现这个 ID 一般是连续生成,所以我直接取后 2 位数字,作为 worker ID
caviar
2021-08-01 12:29:57 +08:00
@Phishion os.getpid() 拿的是系统的 pid,个人并不觉得有连续的保证。uwsgi 提供的 worker id 是从 1 开始连续递增的。就像你前面说的,使用 pid 在大部分情况下不会有问题,但是既然有提供更好的 worker id,为什么不用呢。
Phishion
2021-08-01 13:32:32 +08:00
@caviar 连续不连续实际上无所谓,后面 2 位不重复我觉得就可以了,总不能跳 100 个 PID 再生成第二个,uwsgi 的 worker ID 我还不知道怎么拿,配合重试逻辑,应该已经解决了,所以就没进一步修这个问题。
ysw
2021-08-01 20:29:07 +08:00
可用 redis 的分布式锁

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/792678

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX