Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
如何在高并发下,保证共享数据的一致性_创想鸟

如何在高并发下,保证共享数据的一致性

高并发环境下,要保证共享数据的一致性,核心在于通过一系列严谨的、从数据库到应用架构层面的“并发控制”机制,来确保多个并行的操作,在逻辑上,能够像“串行”执行一样,产生一个确定的、符合业务规则的正确结果。一套全面、健壮的数据一致性保障体系,其构建必须系统性地涵盖五大关键策略:运用“锁”机制保障操作的“互斥性”、通过“事务”确保一系列操作的“原子性”、在分布式系统中选择合适的“一致性模型”、利用“消息队列”等工具实现“最终一致性”、以及在架构设计层面采用“无锁”或“数据分片”等策略。其中,通过“事务”确保一系列操作的“原子性”,是保障数据一致性的“基石”。

如何在高并发下,保证共享数据的一致性如何在高并发下,保证共享数据的一致性

一个事务,就如同一个“保险箱”,它将一系列独立的数据库读写操作,都包裹在了一个“要么全部成功、要么全部失败”的、不可分割的单元之中。如果在事务执行的过程中,发生了任何错误,整个事务,都会被“回滚”到操作开始前的原始状态,从而,从根本上,杜绝了数据,因为“操作执行了一半”而被遗留在一种“中间的、不一致的”残缺状态的风险。

一、问题的根源、并发下的“数据混沌”

在探讨“如何保证”之前,我们必须首先,深刻地,理解“为何会不一致”。在单用户、低并发的环境中,数据的一致性,通常是自然而然的。然而,一旦进入高并发的世界,多个用户或进程,在几乎同一微秒,对同一个共享数据,进行“读取-修改-写回”的操作时,一场“数据的混沌”风暴,就将不可避免地降临

1. 经典的“商品库存”场景

这是一个最能直观地,揭示并发问题所在的经典案例:

场景:一件热门商品,其在数据库中的库存,只剩下最后1件。

并发事件:在几乎完全相同的时间点,用户A和用户B,都点击了“购买”按钮。这两个请求,被分配到了服务器的两个不同线程(线程A和线程B)上,并行地开始处理。

一个未经保护的、灾难性的执行时序

时刻1:线程A,从数据库中,读取商品库存,得到值为1

时刻2:线程A,在内存中,进行逻辑判断:1 > 0,库存充足,可以购买。

时刻3此时,发生了一次线程切换! 操作系统,暂停了线程A的执行,转而去执行线程B。

时刻4:线程B,也从数据库中,读取商品库存。因为线程A的修改,尚未被写回,所以,它读取到的值,依然1

时刻5:线程B,在内存中,也进行了逻辑判断:1 > 0,库存充足,可以购买。

时刻6:线程B,执行“写回”操作,将库存修改为1 - 1 = 0,并更新到数据库中。然后,为用户B,创建了订单。

时刻7线程再次切换,回到线程A。

时刻8:线程A,从上次被暂停的地方,继续执行。它基于自己早已“过时”的、在时刻1读取到的旧数据,执行“写回”操作,将库存,再次,修改为1 - 1 = 0,并为用户A,也创建了订单。

最终结果:一件商品,被成功地,卖给了两个人。数据库中的库存,变为了-1(如果字段允许负数)。数据,进入了严重的“不一致”状态。

2. 一致性的“定义”

数据一致性,是指数据,在其生命周期中的任何时间点,都必须,处于一种符合预设业务规则的、有效的、逻辑自洽的状态。例如,“商品库存,永远不能为负数”,就是一条业务规则。

二、方案一、“单体”世界中的“强一致性”

对于那些运行在“单个”数据库服务器上的、传统的“单体”应用而言,我们通常,会追求一种最高级别的、可立即验证的“强一致性”。

1. “锁”机制:从“悲观”到“乐观”

“锁”,是实现并发控制的、最基础、也最直接的工具。

悲观锁:它秉持一种“悲观”的哲学,即“假设冲突,总是会发生”。因此,它在对数据,进行任何操作之前,会先** preemptively**地,将这条数据“锁定”。

实现方式:例如,在数据库中,使用SELECT ... FOR UPDATE语句。当一个事务,执行了这条语句后,数据库,就会将该行数据锁定。任何其他的事务,如果也想修改这一行,就必须“排队等待”,直到前一个事务,完成并“释放”锁为止。

优缺点数据一致性保障极高,但因为“串行化”了并行操作,所以,会牺牲掉一部分的“并发性能”

乐观锁:它秉持一种“乐观”的哲学,即“假设冲突,是小概率事件”。它不会在操作前加锁,而是在**最终“提交更新”**的那一刻,去检查,数据,是否已经被其他线程所修改。

实现方式:通常,会在数据表中,增加一个“版本号”字段。

线程A,读取数据时,会同时读取其“版本号”(例如,v=1)。

当线程A,准备写回数据时,它的更新语句,会变成:UPDATE products SET stock = 0, version = 2 WHERE id = ? AND version = 1

如果,在此期间,线程B,已经抢先一步,修改了库存,那么,该行数据的版本号,就已经变成了2。此时,线程A的UPDATE语句,会因为version = 1这个条件不满足,而更新失败(影响行数为0)。

优缺点并发性能,远高于悲观锁。但如果“冲突”频繁发生,那么,大量的“重试”操作,反而会降低整体性能。

2. 数据库“事务”:原子性的保障

事务,是将一系列独立的数据库读写操作,打包成一个“不可分割”的、“要么全部成功,要么全部失败”的“原子”单元的、最核心的机制。 一个符合ACID标准(即原子性、一致性、隔离性、持久性)的事务,能够从根本上,保障在一个操作序列中的数据一致性。 在开篇的“商品库存”案例中,只要我们将“读取库存 -> 判断库存 -> 修改库存”这三个步骤,完整地,包裹在一个“事务”中,并配合“悲观锁”,那么,当线程A,在事务中,执行SELECT ... FOR UPDATE时,线程B的SELECT ... FOR UPDATE请求,就会被阻塞,直到线程A的整个事务,提交回滚为止。

三、挑战的“升维”:分布式系统的一致性

当我们的业务,发展到需要将数据,分散存储在多个独立的服务器(即“分布式系统”)上时,一致性的保障,其难度,会呈指数级上升。

1. CAP定理的“三难困境”

CAP定理,是分布式系统领域的“基石”理论。它指出,任何一个分布式系统,在以下三个核心指标中,最多,只能同时,满足其中两个

一致性:任何一次读操作,都能读取到“最新的”写操作的结果。

可用性:任何一次请求,都能收到一个“非错误”的响应,但不保证数据是最新的。

分区容错性:系统在遇到“网络分区”(即节点间的网络连接中断)时,依然能够继续对外提供服务。

在现实世界的、一个必然会遇到网络故障的分布式系统中,“分区容错性”,是一个必须被保障的基础。因此,我们,常常被迫地,在“一致性”和“可用性”之间,做出一个艰难的“权衡取舍”。

2. BASE理论与“最终一致性”

为了应对这种“三难困境”,许多大型的互联网系统,都选择,放弃“强一致性”,而遵循“BASE理论”,追求一种更具弹性和扩展性的“最终一致性”。

BASE理论,即基本可用软状态最终一致

最终一致性,意味着,系统,并不保证,在数据写入后的“任何时刻”,所有节点上的数据,都是完全一致的。但它“承诺”,在经过了一个短暂的“不一致窗口期”之后,所有节点上的数据,最终,都将会,达到一个一致的状态。

四、方案二、“分布式”世界中的“最终一致性”

1. 分布式事务的“两阶段提交”与“补偿事务”

为了在分布式环境下,实现多个独立服务之间的“事务性”操作,业界发展出了“两阶段提交”、“补偿事务”等复杂的分布式事务协议。它们,通过引入一个“协调者”的角色,来尽力地,模拟传统单体数据库的事务行为。但因为其实现的复杂性和对性能的巨大影响,在许多互联网场景下,团队更倾向于,采用基于“消息”的、更松耦合的最终一致性方案。

2. 核心模式:基于“消息队列”的异步通信

消息队列(如Kafka, RabbitMQ),是实现最终一致性的、最常用、也最可靠的“核心基础设施”。

场景:在一个电商系统中,“订单服务”,在创建了一个新订单后,需要通知“库存服务”,去扣减库存,并通知“积分服务”,去为用户增加积分。

最终一致性的实现

“订单服务”,在自己的本地数据库事务中,成功地,创建了订单。

然后,它并不直接地,去远程调用“库存服务”和“积分服务”的接口(因为,这些调用,可能会失败或超时)。

取而代之,它,向一个高可用的“消息队列”中,发送一条包含了订单信息的、可靠的“订单已创建”的消息。

“库存服务”和“积分服务”,则作为“消费者”,分别地,“订阅”了这个消息。

当它们,收到这条消息后,再各自地,在自己的服务内部,执行“扣减库存”和“增加积分”的操作。

优点:这种模式,通过“消息中间件”,将原本紧耦合的、同步的调用,进行了解耦,极大地,提升了系统的“可用性”和“弹性”。即便“库存服务”暂时宕机,也不会影响到“订单服务”的正常运行。

五、在流程与实践中“抉择”

一致性,并非一个“越高越好”的单一指标。在不同的业务场景下,我们需要,有策略地,选择不同“级别”的一致性模型

需要“强一致性”的场景:所有与“金钱”和“交易”直接相关的核心流程,例如,支付、下单、核心库存等。在这些场景下,我们必须,不计代价地,采用数据库的“事务”和“悲观锁”等机制,来保障数据的绝对一致。

可接受“最终一致性”的场景:大量的、非交易核心的场景,例如,用户动态的更新、文章点赞数的显示、非核心信息的跨系统同步等。在这些场景下,短暂的数据不一致,对用户体验的影响很小,我们可以,放心地,采用基于“消息队列”的最终一致性方案,来换取系统更高的可用性可扩展性

常见问答 (FAQ)

Q1: “强一致性”和“最终一致性”哪个更好?

A1: 两者并无绝对的“好坏”之分,只有“适用场景”的不同。“强一致性”,提供了最可靠的数据保证,但牺牲了部分的“性能”和“可用性”。而“最终一致性”,则通过接受一个短暂的“不一致”窗口,来换取系统极高的“可用性”和“可扩展性”。

Q2: 什么是“ACID”?

A2: “ACID”,是数据库事务,必须具备的四个核心特性:原子性(一个事务,是不可分割的工作单元,要么全做,要么全不做)、一致性(事务,必须使数据库,从一个一致性状态,转变到另一个一致性状态)、隔离性(并发执行的事务之间,不应相互干扰)和持久性(一旦事务提交,其结果,就是永久性的)。

Q3: 为什么说在分布式系统中,我们必须在“一致性”和“可用性”之间做出选择?

A3: 这是由“CAP定理”所决定的。因为,在分布式系统中,“网络分区”(即网络故障)是不可避免的。当网络分区发生时,一个节点,为了保证“一致性”,就必须拒绝那些可能“过时”的读写请求,从而,牺牲了“可用性”。反之,如果它为了保证“可用性”,而继续处理请求,那么,它所处理的数据,就可能是“过时”的,从而,牺牲了“一致性”。

Q4: “乐观锁”和“悲观锁”有什么区别?

A4: 两者的核心区别,在于对“并发冲突”的“假设”不同。“悲观锁”,假设冲突“很可能会发生”,所以,在操作数据“之前”,就先将其“锁定”。而“乐观锁”,则假设冲突“很少会发生”,所以,它在操作前“不加锁”,而只是在最终“提交更新”时,才去“检查”,在此期间,数据是否已被其他线程修改过。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:百晓生,转转请注明出处:https://www.chuangxiangniao.com/p/638958.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
豆包AI如何实现智能排班 豆包AI人力资源调度功能
上一篇 2025年11月12日 12:45:39
为什么两个线程会互相等待,导致程序“死锁”
下一篇 2025年11月12日 12:45:52

相关推荐

  • Java中如何将嵌套列表对象转换为扁平化单元素列表

    本文探讨了在java中将包含嵌套列表的对象集合转换为新列表的多种策略,旨在使新列表中每个对象仅包含其嵌套列表中的一个元素。通过详细介绍java 7的传统迭代方法、java 8-15的stream api `flatmap`操作,以及java 16及更高版本的`mapmulti`方法,文章提供了清晰的…

    2026年9月21日
    100
  • Java中将包含嵌套列表的对象列表扁平化为单一元素列表的转换技巧

    本文探讨了在java中如何将一个包含嵌套列表的对象列表进行转换,使其生成一个新的列表,其中每个对象内部的嵌套列表只包含一个元素。文章详细介绍了三种实现方式:基于java 7及以前版本的传统循环方法、利用java 8至java 15的stream api结合`flatmap`操作,以及java 16及…

    2026年9月20日
    200
  • Java字符串加密:解决循环中提前返回导致的数字转换问题

    本文深入探讨java中将字符串转换为数字加密时,因`for`循环内不当的`return`语句导致程序提前终止,仅返回首个字符转换值的问题。通过分析原始代码的逻辑缺陷,提供了修正后的`getnumber`方法,确保所有字符都能正确处理并最终组合成完整的加密数字,并优化了`main`方法的调用逻辑,提升…

    2026年9月12日
    300
  • Java中查找整数最小与最大数字的实用教程

    本教程将深入探讨在java中如何高效地从一个整数中提取并找出其包含的最小和最大数字。我们将详细介绍两种主要方法:基于数学运算(取模和除法)的逐位处理,以及将整数转换为字符串后进行字符遍历。通过清晰的示例代码和关键注意事项,帮助开发者掌握这一实用技巧。 在软件开发中,我们有时需要对用户输入的数字进行精…

    2026年9月12日
    100
  • 网易CodeWave发布人工智能开发能力,全面升级企业智能研发新模式

    网易CodeWave发布人工智能开发能力,全面升级企业智能研发新模式网易CodeWave发布人工智能开发能力,全面升级企业智能研发新模式网易CodeWave发布人工智能开发能力,全面升级企业智能研发新模式网易CodeWave发布人工智能开发能力,全面升级企业智能研发新模式

    2025年10月14日,网易codewave举办“用ai重构研发方式”主题沟通会,正式对外发布多项智能开发能力,支持从需求梳理、产品构思、开发部署、迭代等全流程研发智能化。作为面向企业研发场景的开发平台,网易codewave采用可视化与ai融合的开发方式,支持每一步操作可由ai自动完成,同时保留人工…

    2026年9月12日 用户投稿
    100
  • Swoole如何处理高并发?并发瓶颈如何解决?

    Swoole处理高并发的核心在于异步非阻塞I/O与协程。它通过事件循环监听多个连接,仅在数据可读时触发回调,避免阻塞进程,从而高效处理大量并发连接。协程使异步代码同步化,减少回调嵌套,提升可读性与并发性能。Swoole通过多worker进程利用多核CPU,主进程分发连接至worker进程,避免单点瓶…

    2026年9月11日
    100
  • Java java.util.logging 框架中定制化日志消息的实践

    本教程旨在指导开发者如何在 java `java.util.logging` 框架中灵活定制日志消息。通过修改 `logger.log()` 或 `logger.info()` 等方法的参数,开发者可以为每次日志记录提供具体且有意义的上下文信息,从而提升日志的可读性和问题排查效率,避免千篇一律的通用…

    2026年9月10日
    000
  • 在数组中随机放置指定数量且互不相邻的元素

    本文详细阐述了如何在指定大小的字符串数组中,随机放置特定数量的特殊字符,同时确保这些字符彼此不相邻,并用默认字符填充其余位置。教程涵盖了数组初始化、随机索引生成、严格的相邻及边界条件检查,以及确保元素数量精确控制的实现策略,提供完整的Java代码示例和注意事项,旨在帮助开发者构建健壮的随机布局逻辑。…

    2026年9月9日
    600
  • 实践VSCode智能代码混淆器与知识产权保护

    代码混淆可通过VSCode插件或构建工具集成实现,如JavaScript Obfuscator插件或Webpack结合obfuscator库,配合task.json自动化任务。其主要效果包括变量名替换、控制流扁平化、字符串加密和防调试机制,显著提升反向工程难度。但需平衡保护与性能,仅混淆生产代码,排…

    2026年9月9日
    000
  • 使用Java Streams高效过滤嵌套列表并提取数据

    本文详细介绍了如何利用Java Streams处理复杂嵌套数据结构,特别是从包含多层列表的对象中,根据特定条件(如图片格式)过滤数据并提取所需信息。通过结合filter、map和reduce等Stream API操作,展示了如何简洁高效地从产品图片列表中筛选出JPG格式图片的URL,并将其聚合成逗码…

    2026年9月8日
    200
  • 如何在Swoole中使用协程实现高并发的swoole_sntp函数

    swoole是一个高性能的php协程框架,具有协程、异步io、高性能、高并发等特性,非常适合开发网络服务。其中,swoole_sntp函数是用来同步服务器时间的函数,可以在开发中起到非常重要的作用。在本篇文章中,我们将介绍如何在swoole中使用协程实现高并发的swoole_sntp函数。 Swoo…

    用户投稿 2026年9月5日
    100
  • 如何在Swoole中使用协程实现高并发的swoole_ftpdelete函数

    随着互联网的不断发展,我们所编写的网络应用程序需要能够处理大量的并发请求。而现在的网络服务器框架,如swoole,已经开始支持协程模式。协程模式是一种轻量级的线程模型,它可以在同一个线程中并发执行多个任务。在swoole中,使用协程可以大幅度提高服务器的并发处理能力。 Swoole是一个基于PHP编…

    用户投稿 2026年9月5日
    100
  • 如何在Swoole中使用协程实现高并发的swoole_imap_delete函数

    随着互联网的迅猛发展,网络应用的需求越来越高,尤其是对于即时通讯等涉及到高并发、高负载的应用,更是对服务器的性能提出了更高的要求。而 swoole 作为一个全异步、高性能的网络通信框架,自然成为了开发者们的首选。 在 Swoole 中,协程是一种轻量级的线程,常被用于修改同步 I/O 的函数,并制造…

    用户投稿 2026年9月5日
    000
  • Swoole如何使用协程实现高并发swoole_memcached_server

    swoole是一个基于php语言的协程框架,其提供了一个高效的服务端开发框架。在swoole中,我们可以通过使用协程来实现高并发的服务器,而在本文中,我们将讨论如何使用协程来实现一个高并发的swoole_memcached_server。 什么是swoole_memcached_server? 首先…

    用户投稿 2026年9月5日
    100
  • 如何在Swoole中使用协程实现高并发的swoole_pop3函数

    随着互联网的不断发展,高并发已经成为了现代互联网应用中的重要问题之一。在网络应用中,pop3协议是一种常见的电子邮件收发协议,因此在实现高并发的pop3应用时,使用协程成为了一种有效的解决方案。本文将介绍如何在swoole中使用协程实现高并发的swoole_pop3函数。 一、POP3基础知识 PO…

    用户投稿 2026年9月5日
    000
  • 如何在Swoole中实现高并发文件上传

    随着互联网的快速发展,各种类型的网站和应用程序不断涌现,而这些网站和应用程序中,文件上传是一个很重要的功能。而在高并发的情况下,文件上传往往会成为服务器的瓶颈。 Swoole是一个PHP的网络通信框架,具有高效、稳定、异步、并行等特点,被广泛应用于高并发、高性能的网络服务器。本文将介绍如何在Swoo…

    用户投稿 2026年9月5日
    000
  • Swoole如何支持高并发的人工智能服务

    随着人工智能的飞速发展,越来越多的企业开始使用人工智能服务来提高效率和竞争力。然而,高并发处理是人工智能服务面临的一个大挑战,因为它需要同时处理大量的数据请求。在这种情况下,swoole是一种极好的选择,因为它是一种支持高并发的php扩展,可以实现快速、高效地处理大量的数据请求。 首先,Swoole…

    用户投稿 2026年9月5日
    000
  • Apertus— 瑞士开源的首个大规模语言模型

    Apertus— 瑞士开源的首个大规模语言模型Apertus— 瑞士开源的首个大规模语言模型Apertus— 瑞士开源的首个大规模语言模型Apertus— 瑞士开源的首个大规模语言模型

    ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 天工大模型 中国首个对标ChatGPT的双千亿级大语言模型 115 查看详情 Apertus是什么 apertus是瑞士epfl、eth zurich和瑞士国家超级计算中心(cscs)联合推出的…

    2026年9月4日 用户投稿
    200
  • swoole开发功能的高并发TCP长连接处理技巧

    【标题】Swoole开发功能的高并发TCP长连接处理技巧 【导言】随着互联网的高速发展,应用程序对并发处理的需求也越来越高。Swoole作为一款基于PHP的高性能网络通信引擎,提供了强大的异步、多进程、协程能力,极大地提升了应用程序并发处理的能力。本文将介绍如何使用Swoole开发功能的高并发TCP…

    2026年9月4日
    000
  • Swoole开发技巧:如何处理高并发的网络通信

    Swoole开发技巧:如何处理高并发的网络通信 概述:在当今互联网时代,高并发的网络通信是一项非常重要的技术需求。Swoole是一个基于PHP的高性能协程并发网络通信引擎,它提供了强大的异步、协程、并行处理能力,极大地提升了PHP的性能和并发处理能力。本文将介绍如何使用Swoole处理高并发的网络通…

    2026年9月1日
    100

发表回复

登录后才能评论
关注微信