首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

PHP 在高并发的时候同时写入同一条数据,会不会出现数据遗漏的问题?

  •  
  •   cstome · 362 天前 · 942 次点击
    这是一个创建于 362 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目 ThinkPHP+MySQL

    具体是这样,有个文章后台,每条文章有个字段存着已读人员,是数组形式存着 UID,然后 json_encode 存进数据库。

    当访问文章的时候,读取该字段,json_decode 后,判断当前 UID 是否在数组中,不存在则 push 上去,然后再 json_encode 进数据库。

    问题就是当出现高并发的时候(最高大概也就每秒上千个访问),会不会出现多个 PHP 进程同时读取了该字段,然后又同时写入数据库,导致部分数据被覆盖过去。

    同时也想知道有哪些资料可以了解一下 PHP 以及 MySQL 的线程、执行顺序问题。

    8 回复  |  直到 2018-06-20 15:07:09 +08:00
        1
    feiyuanqiu   362 天前
    跟 PHP 没关系,数据库层面可以看看悲观锁、乐观锁,小流量网站用悲观锁一般就解决了
        2
    bestkayle   362 天前 via iPhone
    用队列
        3
    feiyuanqiu   362 天前
    不过我觉得其实应该把已读人员单独弄张表,表里面做个 文章 ID + 用户 ID 的唯一键,插入冲突就表示已经存在这个关系了,直接返回已存在的已读关系,这样接口也幂等了
        4
    allenhu   362 天前
    每秒上千个访问, 你的 uid 字段存得下么?
        5
    cstome   362 天前
    @allenhu #4 实际情况是文章刚发布的时候会有大概最高每秒 1000 的高并发,后面会慢慢下降,UID 也不长,用 TEXT 类型完全够存。
        6
    puritania   362 天前 via iPhone
    强行制造并发……
        7
    cstome   361 天前
    @feiyuanqiu #3 之前想过这么弄,但是考虑到后面可能数据库条数比较多,影响速度,就没这么弄了。
        8
    feiyuanqiu   361 天前   ♥ 1
    @cstome

    怕数据库慢就用 redis,用文章表字段存这个真不太好,我现在能想到的问题就不少了:

    1. 会影响文章表的查询效率,尤其是在阅读人数变多之后,每条文章记录都平白无故增加几 K 的内容
    2. 无法检索用户已读的文章,因为是 json_encode 到 text 里面的,没法做查询,以后产品有这个需求的时候又要改又要做数据迁移
    3. 更新阅读记录效率低下,要先检索出文章,再 decode,再往里面添加内容,再 encode,再更新,还要加锁放并发;比直接插入一条阅读记录效率低多了
    4. text 的长度是 65536,你的 uid 长度是多少,假设是 32,最多可以存 2048 个 uid,实际肯定存不了这么多,因为你还做了 json_encode,也就是一篇文章上限只能存一千多个阅读记录
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   724 人在线   最高记录 5043   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 18ms · UTC 20:42 · PVG 04:42 · LAX 13:42 · JFK 16:42
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1