V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Neil66
V2EX  ›  科技

新增一条数据到数据库,如何可以避免重复(前后端)

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

    软件开发,create 操作,新增一行业务数据到数据库中,用户如果重复点击提交按钮就会导致数据库重复,各位大佬们有哪些解决方案呢?前后端、数据库、架构设计之类方案都可以分享一下

    18 条回复    2022-06-25 08:41:07 +08:00
    qping
        1
    qping  
       49 天前
    百度:防止表单重复提交
    seanzxx
        2
    seanzxx  
       49 天前
    数据库不是有主键和唯一键吗?
    rabbbit
        3
    rabbbit  
       49 天前
    单独有个校验接口,用户输入时前端(节流 300s 一次)调这个接口校验值是否重复,重复则提醒用户。
    后端提交时再校验一次。
    aitaii
        4
    aitaii  
       49 天前
    数据库兜底,前端,网关可以做校验,幂等操作
    66beta
        5
    66beta  
       49 天前
    各做各的,后端是最后的防线
    aitaii
        6
    aitaii  
       49 天前

    流程说明:

    前端服务进入页面从服务端获取 token ,服务端生成 token 放入 redis 返回。
    前端调用业务接口请求时,把 token 携带过去,一般放在请求头部。
    服务端删除 redis 中的 token 并判断是否成功,若成功继续执行业务。
    若删除失败表示是重复操作,直接返回重复标记给 client 。
    rabbbit
        7
    rabbbit  
       49 天前
    问个问题,假如两个人分别在两地修改同一个条数据,后端分布式是如何解决这种数据可能不一致的问题的?
    是只有一个数据库吗?还是多个数据库只有一个写,其他的读?
    wolfie
        8
    wolfie  
       49 天前
    最简单前端 disable 控件。
    后端弄就麻烦了。
    hidemyself
        9
    hidemyself  
       49 天前
    @rabbbit 版本号
    sanmaozhao
        10
    sanmaozhao  
       49 天前
    如果后端本身是允许两条完全一样的数据存在的话,比如用户正常操作两次,只是录入的数据相同
    那这个事情就和后端没有关系了
    前端提交按钮在结果没返回前进入 busy 状态就行
    kyuuseiryuu
        11
    kyuuseiryuu  
       49 天前 via iPhone   ❤️ 1
    本质上还是怎么区分两条一模一样的数据是
    “确实想造两条一样的数据”这个需求来的,还是“不小心重复请求”这个异常

    一般创建接口就是创建。

    为了用户不误操作就前端坐处理,创建成功后做好提示,展示成功页面。

    后段不放心就做请求限制,重复请求拦截的时间限制不应该大于用户正常填写完表单的时间。
    BugCry
        12
    BugCry  
       49 天前 via Android
    关键词:幂等性、nonce 、timestamp
    duanxianze
        13
    duanxianze  
       48 天前
    本质上还是先看你的需求,如果只是发微博这种,其实靠前端限制就行,后端设置个请求频次限制,如果是银行交易,那就复杂了,没搞过,不多说了
    aecra1
        14
    aecra1  
       48 天前 via Android
    @rabbbit CAP 定理,一致性 /可用性 /分区容错性不可同时满足,根据业务取舍
    cvbnt
        15
    cvbnt  
       48 天前 via Android
    redis 做幂等性提交,大致是 6 楼的过程,在删除的过程中为了保证事务,推荐用 lua 脚本删除,比如
    if redis.call("get",KEYS[1])==ARGV[1] then
    return redis.call("del",KEYS[1])
    else
    return 0
    end
    如果 redis 环境是集群,可能需要对键值做额外设置
    nigulasida
        16
    nigulasida  
       48 天前
    pg 可以 insert-up
    EscYezi
        17
    EscYezi  
       48 天前 via iPhone
    前端点击后加 loading ,后端每次请求开始加个单个用户级别 redis 锁,请求结束释放(或者结束一秒后过期)。一次请求期间如果同一个用户再次发起请求直接返回操作频繁,基本上可以避免重复提交。也可以做成用户&接口粒度的。
    sunnysab
        18
    sunnysab  
       48 天前
    @nigulasida insert-up 是 insert update 吗?
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4232 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 06:46 · PVG 14:46 · LAX 23:46 · JFK 02:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.