V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
sing1ee
V2EX  ›  程序员

踩了 MongoDB 的一个小坑

  •  1
     
  •   sing1ee · May 15, 2015 · 6119 views
    This topic created in 4008 days ago, the information mentioned may be changed or developed.

    先了解几个基本点:
    1. MongoDB默认生成的ObjectId是在客户端完成的,时间戳+host+进程id等,详情见文档
    2. ObjectId生成的时候,是根据当期那服务器时间所在的时区
    3. 从collection中读出ObjectId,读取generation_time属性,默认是UTC
    4. 北京时间比UTC时间早了八个小时

    我们两台服务器,一个是北京时间,一个比北京时间早了八个小时。。。从这两个服务器入库MongoDB,并且根据generation_time读,就彻底乱了,结果
    1. 北京时间的服务器,得到的generation_time时间比北京时间晚了八个小时
    2. 比北京早了的服务器,得到的generation_time时间和北京时间相同

    我们以为2是正确的。。。

    我们用的是pymongo

    21 replies    2015-05-17 17:00:57 +08:00
    ZackYang
        1
    ZackYang  
       May 15, 2015
    我都是用 uuid 改写...
    jiangzhuo
        2
    jiangzhuo  
       May 15, 2015
    做集羣 肯定要集羣間使用的時間統一的,特別是這種生成唯一性和時間有序的id的時候
    yueyoum
        3
    yueyoum  
       May 15, 2015   ❤️ 2
    这点还真没注意。

    我现在基本都用 UUID 做主键。 无论是 mysql, postgresql 还是 mongodb

    简单,方便。 uuid4 冲突几率是有, 如果你能碰到, 也算是你的运气。

    什么 分布式, 唯一ID生成, 数据库合并, 瞬间解决。



    特别方便的一个使用例子是 django orm 的 bulk_create, 如果你的主键是 自增长 int
    那么 返回的 列表中 对象是没有 id 属性的。

    这时候用UUID 先给对象赋予ID, bulk_create 返回的对象就是带有ID属性的。

    这在 bulk_create后, 需要这些新增加对象ID 的情况 特别有用。


    再说一个场景吧。

    曾经有个项目, 一个server 对应一个 db, 用的 mongodb,

    因为担心效率问题,没有上全局ID生成服务。

    是每个server自己算的, 算法大概是 PARAM * NEWID + SERVER_ID

    param 是一个定义好的数值,比如 1024,
    newid 是这个server 自己生成的唯一自增长ID, 比如 1,2,3,4...
    server_id 就是这个 server 的 id, 不同server 的 id 不一样。

    这样生成好处是 方便,快速
    但缺点也很明显

    能开多少server 是由 param 来决定的, 最多 param 个



    所以,上UUID, 上面问题一锅端。


    有同学会说 INT ID 好啊, 数字的,自然就排序了,
    mongo 的 objectid 好啊, 还带有时间戳, 也可以排序。


    大不了在记录中增加一个 create_at 字段就行,
    相比上面的问题, 增加一个带索引的列,根本不是问题
    kslr
        4
    kslr  
       May 15, 2015
    这不是mongodb的坑,这么多机器时间还不统一,另外 create_at和update_at
    cloudzhou
        5
    cloudzhou  
       May 15, 2015
    @yueyoum 但是使用 uuid 会不会引起性能的减退呢,字段这么长
    sing1ee
        6
    sing1ee  
    OP
       May 15, 2015 via iPhone
    @kslr 时间同步,有什么好方案么
    likuku
        7
    likuku  
       May 15, 2015   ❤️ 1
    @sing1ee 配置好 ntpd 服务啊,每台服务器都运行它。ntpd 是渐进式校准服务器时钟,不会引起时钟误差颠簸(有些服务/软件假若侦测到时钟颠簸,可能会终止运行/运行不正常)。
    likuku
        8
    likuku  
       May 15, 2015
    @sing1ee 关于时钟颠簸/跃变 会引起问题,参考:

    AsiaBSDCon上说OpenBSD的sensor framework的时候的一个观点 - delphij's Chaos : https://blog.delphij.net/2007/03/asiabsdconopenb.html
    mko0okmko0
        9
    mko0okmko0  
       May 15, 2015
    统一使用格林威治时间.直接存成秒数字.一般索引提速.需要时间索引则另用函数生成索引.
    springwarm
        10
    springwarm  
       May 15, 2015
    楼主给出的基本点,"北京时间比UTC时间早了八个小时",会不会有问题

    UTC 和本地时间的换算公式是:
    UTC + 时区差 = 本地时间

    北京是东八区,对应的公式应该是:
    UTC + (+0800) = 北京时间

    以此推断,是UTC 时间比北京时间早了八个小时吧
    sing1ee
        11
    sing1ee  
    OP
       May 15, 2015
    @springwarm 这个应该是北京早吧=;=
    Landarky
        12
    Landarky  
       May 16, 2015 via iPad
    不仅是时区问题 机器时间也可能差几分钟 修改到一致就好
    likuku
        13
    likuku  
       May 16, 2015
    @Landarky 修改机器时间...都21世纪了,没啥理由不用ntpd吧。如今桌面的 ubuntu/osx/windows都默认安装并开启ntpd服务的了。
    xiaogui
        14
    xiaogui  
       May 16, 2015
    UTC 并不是问题,都采用 UTC 最好了。
    whatisnew
        15
    whatisnew  
       May 16, 2015
    我用 mongodb 试着删除 where asc 顺序的前 30 行记录,折腾了半小时 remove findandmodify 都没搞定,然后,我就撤退了。。。
    makuta
        16
    makuta  
       May 16, 2015
    做Mongo集群
    ddou
        17
    ddou  
       May 16, 2015
    个人觉得是使用方式不对,ObjectId当ID用就行了,其他时间的话应该是CreatedAt和UpdatedAt
    Cu635
        18
    Cu635  
       May 16, 2015
    @springwarm 北京时间比UTC早。UTC的1:00am是北京时间当天的9:00am。
    Cu635
        19
    Cu635  
       May 16, 2015
    @springwarm 计算公式是
    1:00am(UTC)+(+0800)(东八区)=9:00am(北京时间,东八区时间)
    VirgilMing
        20
    VirgilMing  
       May 17, 2015 via iPhone
    我很好奇哪个时区比 UTC+8 还 +8?
    springwarm
        21
    springwarm  
       May 17, 2015
    @Cu635 @sing1ee
    知道我的问题出在哪了,我自行换做另外一种说法来理解:同一个时刻,用UTC表示比用北京时间表示,数值“小” (无所谓早晚之分,只是表示法不同)
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   993 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 23:18 · PVG 07:18 · LAX 16:18 · JFK 19:18
    ♥ Do have faith in what you're doing.