安全架构-幂等性设计-SQL
发布日期:2021-05-20 05:11:42 浏览次数:17 分类:精选文章

本文共 2298 字,大约阅读时间需要 7 分钟。

安全架构-幂等性设计:从SQL操作入手

幂等性设计是保证系统在对数据进行操作时,不会因为重复操作而导致数据错误或业务逻辑异常的一种方法。虽然幂等性设计可以分为API幂等性、HTTP幂等性和SQL幂等性,但它们的核心目标都是确保数据操作的唯一性和可靠性。在本文中,我们将从SQL操作的角度深入探讨如何设计SQL幂等性的解决方案。


SQL幂等场景

在实际开发中,SQL操作中的幂等性问题主要体现在以下几个方面:

  • 查询操作

    查询操作通常不会修改数据,例如 select * from user where xxx。这种操作由于不改变数据,因此本质上具备幂等性。

  • 新增操作

    对于新增操作,如果数据库表中有唯一主键约束(如userid),则重复插入数据不会导致数据重复,操作结果是一致的。然而,如果主键并非唯一约束,重复插入数据则会导致数据冗余,严重影响幂等性。

  • 修改操作

    修改操作的幂等性取决于更新字段的类型。

    • 直接赋值:更新字段的值不会因多次执行影响最终结果。例如,update user set point = 20 where userid=1。无论执行多少次,这条记录的point值不变。
    • 计算赋值:更新字段时依赖于当前数据的值,例如 update user set point = point + 20 where userid=1。这种操作会导致数据逐步增加,每次修改都会改变数据状态,因此不具备幂等性。
  • 删除操作

    如果删除操作针对特定记录(如通过主键或唯一标识符),多次执行删除操作不会影响结果,例如 delete from user where userid=1。这种操作本质上具备幂等性。

  • 从以上分析可以看出,在没有唯一主键约束或涉及计算赋值操作的场景下,SQL操作可能会导致幂等性问题。


    解决方案

    针对上述问题,我们可以采用以下几种解决方案:

    1. Token机制

    Token机制是解决幂等性问题的常用方法之一,类似于API接口的幂等性设计。其核心思想是在每次业务操作前,服务端生成唯一的Token,并将该Token存储到缓存(如Redis)中。具体流程如下:

  • 服务端接口提供Token获取:在编写业务逻辑前,先调用服务端的Token获取接口。
    • Token生成后,由服务端将该Token存储到Redis中。
  • 业务接口请求传递Token:在实际业务操作中,将生成的Token添加到请求头中传递。
  • 服务端检查Token状态
    • 如果Token存在于Redis中,表示这是第一次请求,继续执行业务逻辑操作。
    • 如果Token不存在,表示重复请求,直接返回错误标识,避免重复执行操作。
  • Redis删除Token:业务操作成功后,服务端删除Redis中的Token以避免重复请求。
  • 关键点排除

    • 上述流程中的关键在于Token的存取时间。如果Token在Redis中存在的时间过短,可能会导致频繁的重试操作。
    • 标准方案中,Token通常在生成后立即删除或延迟删除。不过,延迟删除的机制需要谨慎处理,以避免数据一致性问题。

    推荐方案:

    在实际开发中,可以参考已有的开源方案(如知乎文章博客等),其中提到的token+redis方案适用于绝大多数场景。

    优点

    • 代码逻辑简单易懂。
    • 在大多数情况下能有效防止重复请求带来的问题。

    缺点

    • 额外生成和验证Token会增加系统的硬件负载,尤其是在高并发场景下。
    • 如果Redis发生障碍或网络分割,可能会导致Token无法及时被删除,从而引发幂等性问题。

    2. 乐观锁机制

    乐观锁机制通过在SQL语句中加入版本号来实现幂等性设计。具体步骤如下:

    • 在SQL操作中添加版本号字段version。例如:
      update user set point = point + 20, version = version + 1 where userid=1 and version=1
    • 在修改操作前,查询当前记录的版本号。如果版本号与期望值一致,说明该记录未被其他操作修改过,可以执行操作。

    优点

    • 能够有效防止多次修改同一记录导致的不确定性。
      -
      代码实现简单。

    缺点

    • 需要在每次操作前先查询当前记录的状态,增加了数据库的IO负载。
    • 适用于单对象锁的情况,不适用于分布式系统中的多个节点操作。

    3. 唯一主键机制

    通过数据库的唯一主键约束来实现幂等性设计。以下是具体实现方式:

  • 主键约束

    在插入操作中,如果数据库表中设置了唯一主键(如useriduuid),则重复插入操作会自动失败。

  • 去重表机制

    为了避免主键冲突,尤其是在分布式系统中,可以引入去重表。具体流程如下:

    • 插入去重表中,确保唯一性。
    • 然后执行实际的业务更新操作。
    • 这两步骤需在同一个事务中完成,确保数据一致性。
  • 优点

    • 适用于需要严格控制唯一性但不想引入外部锁机制的场景。
    • 与数据库本身的约束机制无缝结合,实现简单。

    缺点

    • 对于分布式系统,需要通过投递规则确保同一请求在同一数据库和表中执行,否则主键约束将失效。
    • 可能需要引入额外的去重表和leases管理,增加了系统的复杂性。

    总结

    通过以上几个方法,我们可以针对不同的场景设计适合的SQL幂等性解决方案。在选择具体方案时,需要根据实际业务需求进行权衡,例如:

    • 如果业务场景注重并发性和高性能,推荐使用Token机制。
    • 如果业务涉及多个分布式节点或需要强一致性,建议使用去重表机制。
    • 如果目标是实现在单hic hitter环境中,乐观锁机制是一个不错的选择。

    通过合理的设计和优化,可以有效避免幂等性问题,保障系统的稳定性和数据一致性。

    上一篇:使用 Kubectl 管理 Kubernetes 容器平台
    下一篇:cmd命令行把bat或exe执行为windows服务

    发表评论

    最新留言

    表示我来过!
    [***.240.166.169]2025年05月01日 04时56分59秒