下单时如何保证数据一致性?

news2024/11/18 23:40:03

原创 哪吒 哪吒编程 2023-09-07 08:03 发表于辽宁

收录于合集#Redis11个

 

(给哪吒编程加星标,提高Java技能)

大家好,我是哪吒。

在前几篇文章中,提到了Redis实现排行榜、Redis数据缓存策略,让我们对Redis有了进一步的认识,今天继续进修,了解一下Redis在下单时是如何保证数据一致性的?

例如,在高并发访问下,可能会有多个请求同时读取同一份缓存数据,然后进行写操作,这就容易产生数据竞争的情况。同时,读写操作并不是原子性操作,可能在读取数据的时候,缓存已经被其他请求更新掉,从而导致数据不一致。

为了解决Redis缓存的数据一致性问题,我们需要做到以下两点:

  1. 保证所有请求都是读取最新的数据

  2. 保证所有更新操作都是互斥的并且按照请求的顺序执行

图片

在一个在线商城系统中,面临一个重要的问题:如何在订单支付过程中保证数据的一致性,并且如何优化支付操作的性能。

1、订单支付需求

在用户下单后,需要执行订单支付操作,确保支付和订单状态的一致性。

2、数据一致性要求

支付成功后,必须将订单状态更新为已支付,以保持数据的一致性。

3、高并发支付

在高并发的情况下,需要确保订单支付的性能和数据一致性。

为了解决以上问题,我们可以使用Redis提供的事务和管道机制。

一、Redis事务

1、什么是Redis事务

图片

在Redis中,事务是一组命令的集合,可以在一个单独的流程中执行,以保证这些命令的原子性、一致性、隔离性和持久性。

(1)事务概述

Redis事务由以下四个关键命令进行管理:

命令描述
MULTI开启事务,标记事务块的开始。
EXEC执行事务中的所有命令。
DISCARD取消事务,放弃所有已经入队的命令。
WATCH监视一个或多个键,用于乐观锁。

(2)Redis的事务特性

Redis事务具有以下关键特性:

事务特性描述
原子性事务中的所有命令要么全部执行,要么全部不执行。这确保了在事务执行期间,不会发生部分命令执行成功而部分命令执行失败的情况。
一致性事务中的命令会按照被添加的顺序执行,不会被其他客户端的命令打断。这保证了事务中的操作按照期望的顺序执行,不会受到并发操作的影响。
隔离性在事务执行期间,事务会被隔离,不会受到其他事务的影响。即使有其他并发事务在执行,事务中的操作也不会被其他事务看到,直到事务被执行提交。
持久性事务执行结束后对数据库的修改将被持久化到磁盘上。这确保了事务中的操作不会因为系统故障而丢失,从而保证了数据的持久性。

以上是Redis事务的基本概念和特性,它们保证了在Redis中执行的事务是可靠的、具备一致性的操作集合。

图片

上图形表示了Redis事务的关键特性之间的相互关系。这些特性相互支持,共同确保了Redis事务的可靠性和一致性。

  1. 原子性保证了事务中的操作要么全部成功,要么全部失败。

  2. 一致性保证了事务中的操作按照特定的顺序执行,不会受到其他操作的干扰。

  3. 隔离性确保了事务在执行期间与其他事务相互隔离,互不干扰。

  4. 持久性确保了事务执行后的修改会被持久保存,不会因系统故障而丢失。这些特性一起构成了Redis事务的可靠性和稳定性的基础。

2、使用Redis事务

(1)开始和提交事务

在Redis中,使用事务需要遵循以下步骤:

  1. 使用MULTI命令开启事务。

  2. 执行需要在事务中执行的命令。

  3. 使用EXEC命令提交事务,执行事务中的所有命令。

下面是一个使用Java代码示例的详细步骤:

// 创建与Redis服务器的连接
Jedis jedis = new Jedis("localhost", 6379);

// 开启事务
Transaction transaction = jedis.multi();

// 执行事务中的命令
transaction.set("key1", "value1");
transaction.set("key2", "value2");

// 提交事务并获取执行结果
List<Object> results = transaction.exec();

在上面的示例中,transaction.set("key1", "value1") 和 transaction.set("key2", "value2") 这两个命令会被添加到事务队列中,当transaction.exec()被调用时,事务中的所有命令会被一起执行。如果在MULTIEXEC之间有错误发生,事务会被取消,命令不会执行。

(2)事务命令

在事务中,您可以使用常规的Redis命令,例如SETGETHSETZADD等等。这些命令会被添加到事务队列中,直到执行EXEC命令。

(3)事务示例

以下是使用Java代码示例来演示在事务中执行常见的Redis命令:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class RedisTransactionCommandsExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        // 开启事务
        Transaction transaction = jedis.multi();

        // 执行事务中的命令
        transaction.set("name", "Alice");
        transaction.hset("user:1", "name", "Bob");
        transaction.zadd("scores", 100, "Alice");
        transaction.zadd("scores", 200, "Bob");

        // 提交事务并获取执行结果
        List<Object> results = transaction.exec();

        // 打印执行结果
        for (Object result : results) {
            System.out.println("Result: " + result);
        }

        // 关闭连接
        jedis.close();
    }
}

在上述示例中,使用了SETHSETZADD命令,这些命令被添加到了事务队列中。当执行transaction.exec()时,事务中的所有命令会被一起执行。这里的示例是简单的演示,您可以根据需要添加更多的命令来构建更复杂的事务。

图片

二、Redis管道

1、什么是Redis管道

Redis管道(Pipeline)是一种优化Redis操作的技术,它允许在单次通信中发送多个命令到Redis服务器,从而显著减少了通信开销,提高了性能。

管道可以将多个命令一次性发送给服务器,而不需要等待每个命令的响应,这使得Redis能够更高效地处理批量操作和大规模数据的读写。

下图展示了Redis管道的工作原理:

图片

在上图中,客户端(Client)向Redis服务器(Server)发送多个命令,每个命令用Command 1Command 2等表示。这些命令被一次性发送到服务器,而不需要等待每个命令的响应。服务器在执行所有命令后,一次性将结果响应给客户端。同时说明了Redis管道的工作方式:通过将多个命令打包成一次通信,减少了每个命令的通信开销,提高了系统的性能。

使用Redis管道时,客户端通过创建一个管道对象,将多个命令添加到管道中,然后一次性执行管道中的命令。最后,客户端可以收集所有命令的执行结果。

(1)管道概述

在Redis中,管道是通过以下命令进行管理:

命令描述
PIPELINE开启管道模式,用于一次性发送多个命令。
MULTI开启事务模式,用于在管道中执行一系列命令。
EXEC提交管道中的事务,执行并返回结果。

使用管道,您可以将多个命令一次性发送给服务器,然后通过一次通信获得所有命令的执行结果,从而减少了每个命令的通信开销,提高了系统的性能。

(2)Redis的管道特性

使用Redis管道可以获得以下优势:

  • 减少通信开销: 在普通的命令传输中,每个命令都需要来回的网络通信,而管道可以将多个命令打包一次性发送给服务器,从而大大减少了通信开销。这对于网络延迟较高的场景尤为重要,有效提高了性能。

  • 提高吞吐量: 管道允许在一次通信中执行多个命令,从而在单位时间内处理更多的命令。这对于需要处理大量命令的场景,如批量数据处理、并发请求处理等,能够有效提高Redis的吞吐量和响应能力。

2、使用Redis管道

(1)管道命令

以下是一个实际案例,展示如何使用Redis管道来执行多个命令并提高性能:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;

public class RedisPipelineExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);

        // 创建管道
        Pipeline pipeline = jedis.pipelined();

        // 向管道中添加命令
        for (int i = 0; i < 10000; i++) {
            pipeline.set("key" + i, "value" + i);
        }

        // 执行管道中的命令
        List<Object> results = pipeline.syncAndReturnAll();

        // 关闭连接
        jedis.close();
    }
}

在上述案例中,使用了一个循环来向管道中添加10000个SET命令。通过使用管道,可以在一次通信中将所有命令发送到服务器,而不是逐个发送,从而减少了通信开销,提高了性能。

(2)管道优化性能

使用Redis管道可以提高性能,特别是在需要批量处理多个命令的情况下。管道的原理是一次性将多个命令发送给服务器,然后一次性获取结果,这减少了通信的往返次数,从而显著提高了吞吐量。

然而,需要注意以下几点:

  • 管道不支持事务,不能保证多个命令的原子性执行。

  • 使用管道时,命令的执行顺序可能与添加顺序不一致,这需要根据业务需求进行考虑。

  • 管道并非在所有场景下都能带来性能提升,需要根据实际情况进行评估。

通过合理使用管道,可以最大限度地发挥Redis在高性能数据处理中的优势。

图片

三、事务 vs 管道:何时使用何种

1、事务的适用场景

事务在某些场景下可以保证原子性和一致性的操作,特别适用于强一致性要求的业务操作,例如支付操作。

(1)强一致性操作

事务是一种适用于需要强一致性操作的机制。当多个命令需要在一个操作序列中原子性地执行时,事务可以确保这些命令要么全部执行,要么全部不执行,以保持数据的一致性。

在以下示例中,模拟一个银行转账操作,其中需要同时扣减一个账户的余额并增加另一个账户的余额:

Jedis jedis = new Jedis("localhost", 6379);

// 开启事务
Transaction transaction = jedis.multi();

// 扣减账户1余额
transaction.decrBy("account1", 100);

// 增加账户2余额
transaction.incrBy("account2", 100);

// 提交事务并获取执行结果
List<Object> results = transaction.exec();

// 关闭连接
jedis.close();

(2)原子性要求高

当业务要求多个操作要么全部成功,要么全部失败时,事务是更好的选择。事务确保了事务中的一系列命令以原子操作方式执行,从而维护了数据的一致性。

2、管道的适用场景

管道适用于需要批量操作和吞吐量要求较高的场景。通过一次性发送多个命令到服务器,可以减少通信开销,提高性能。

(1)批量操作

使用管道可以有效地执行批量操作。例如,当您需要向数据库中添加大量数据时,使用管道可以减少每个命令的通信成本,从而大大提高操作的效率。

以下示例演示了如何使用管道进行批量设置操作:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import java.util.List;

public class RedisPipelineBatchExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        Pipeline pipeline = jedis.pipelined();

        // 向管道中添加一批设置操作
        for (int i = 0; i < 1000; i++) {
            pipeline.set("key" + i, "value" + i);
        }

        // 执行管道中的命令
        List<Object> results = pipeline.syncAndReturnAll();

        // 关闭连接
        jedis.close();
    }
}

(2)吞吐量要求高

在需要高吞吐量的场景下,管道可以显著提升性能。当多个命令需要在短时间内执行时,使用管道可以将这些命令打包发送,减少了通信的往返次数。

使用管道来进行大规模数据处理时,尤其可以在高负载的情况下提高系统的处理能力。

图片

四、案例研究:保证订单支付的数据一致性与性能优化

1、场景描述

在一个在线商城系统中,面临一个重要的问题:如何在订单支付过程中保证数据的一致性,并且如何优化支付操作的性能。

(1)订单支付需求

在用户下单后,需要执行订单支付操作,确保支付和订单状态的一致性。

(2)数据一致性要求

支付成功后,必须将订单状态更新为已支付,以保持数据的一致性。

(3)高并发支付

在高并发的情况下,需要确保订单支付的性能和数据一致性。

2、使用Redis事务解决数据一致性问题

(1)事务实现订单支付

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 扣除用户余额
transaction.decrBy("user:balance:1", orderAmount);

// 更新订单状态为已支付
transaction.hset("order:1", "status", "paid");

List<Object> results = transaction.exec();

以上示例中,使用了Redis事务来确保在一个操作序列中,用户余额的扣除和订单状态的更新同时发生。如果事务中的任何一步操作失败,整个事务都会被回滚,保证了数据的一致性。

(2)事务的一致性保证

使用事务可以保证用户余额和订单状态的一致性,要么同时成功,要么同时失败。这样,可以确保支付和订单状态的正确性,避免了潜在的数据不一致问题。

3、使用Redis管道优化支付性能

(1)管道批量支付

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (Order order : orders) {
    pipeline.decrBy("user:balance:" + order.getUserId(), order.getAmount());
    pipeline.hset("order:" + order.getId(), "status", "paid");
}

List<Object> results = pipeline.syncAndReturnAll();

在这个示例中,使用了Redis管道来批量处理多个订单的支付。通过将多个命令一次性发送给服务器,可以减少通信开销,从而显著提高支付操作的性能。

(2)管道的性能提升

通过使用管道,可以将多个支付操作打包在一次通信中进行,减少了通信往返次数,从而提高了支付的性能。

尤其在高并发支付的场景下,管道可以显著减少服务器负载,提高系统的响应能力。

图片

五、事务和管道的限制与注意事项

1、事务的限制

事务在使用过程中需要注意以下限制,其中包括WATCH命令和乐观锁的使用。

(1)WATCH命令

在事务中使用WATCH命令可以监视一个或多个键,如果被监视的键在事务执行过程中被其他客户端修改,事务会被中断。这是为了保证事务的一致性和避免竞态条件。

正面例子:

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 监视键"balance"
transaction.watch("balance");

// ... 在此期间可能有其他客户端修改了"balance"键的值 ...

// 执行事务
List<Object> results = transaction.exec();

反面例子:

Jedis jedis = new Jedis("localhost", 6379);
Transaction transaction = jedis.multi();

// 监视键"balance"
transaction.watch("balance");

// ... 在此期间其他客户端修改了"balance"键的值 ...

// 尝试执行事务,但由于"balance"键被修改,事务会被中断
List<Object> results = transaction.exec();

(2)乐观锁

在处理并发更新时,可以使用乐观锁的方式。通过使用版本号或时间戳等机制,在执行命令前先检查数据是否被其他客户端修改过,从而避免并发冲突。

正面例子:

Jedis jedis = new Jedis("localhost", 6379);

// 获取当前版本号
long currentVersion = Long.parseLong(jedis.get("version"));

// 更新数据前检查版本号
if (currentVersion == Long.parseLong(jedis.get("version"))) {
    Transaction transaction = jedis.multi();
    transaction.set("data", "new value");
    transaction.incr("version");
    List<Object> results = transaction.exec();
} else {
    // 数据已被其他客户端修改,需要处理冲突
}

2、管道的注意事项

使用管道时需要注意以下事项,包括管道的串行性和慎重使用。

(1)不支持事务

管道不支持事务,因此无法通过管道实现事务的原子性和一致性。如果需要事务支持,应该使用Redis的事务机制。

(2)慎用管道

管道虽然可以提高性能,但并不是在所有场景下都能带来性能提升。在某些情况下,由于管道的串行性,某些命令可能会阻塞其他命令的执行,反而降低了性能。

正面例子:

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (int i = 0; i < 1000; i++) {
    pipeline.set("key" + i, "value" + i);
}

// 执行管道中的命令并获取结果
List<Object> results = pipeline.syncAndReturnAll();

反面例子:

Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();

for (int i = 0; i < 1000; i++) {
    // 注意:此处执行了耗时的命令,可能阻塞其他命令的执行
    pipeline.get("key" + i);
}

// 执行管道中的命令并获取结果
List<Object> results = pipeline.syncAndReturnAll();

六、总结

本篇博客深入探讨了Redis中的事务和管道机制,以及它们在保证数据一致性和优化性能方面的应用。

通过详细的讲解和代码示例,我们了解了事务和管道的基本概念、特性、使用方法以及适用场景。以下是本篇博客的主要内容总结:

Redis事务部分,我们了解了事务的概念和特性。事务可以确保一系列命令的原子性、一致性、隔离性和持久性。

通过MULTI、EXEC、DISCARD和WATCH命令,我们可以管理事务的开始、提交、回滚以及监视键变化。事务适用于需要保证原子性和一致性的操作,特别是在强一致性要求的场景下。

Redis管道部分,我们深入了解了管道的概念和优势。管道允许一次性发送多个命令到服务器,减少通信开销,提高性能。

通过PIPELINE、MULTI和EXEC命令,我们可以创建管道、添加命令,并执行管道中的命令。管道适用于批量操作和吞吐量要求较高的场景,可以显著提高Redis的性能。

事务 vs 管道:何时使用何种部分,我们对比了事务和管道的适用场景。

  1. 事务适用于保证强一致性操作和原子性要求高的场景;

  2. 管道适用于批量操作和高吞吐量的场景。

通过示例,我们说明了如何根据业务需求选择合适的机制来满足一致性和性能的需求。

案例研究:保证订单支付的数据一致性与性能优化部分,我们应用之前的知识解决了一个实际问题。我们展示了如何使用事务保证订单支付的数据一致性,同时如何使用管道优化支付操作的性能。这个案例充分体现了事务和管道在实际业务中的应用。

事务和管道的限制与注意事项部分,我们指出了事务和管道的一些限制和注意事项。事务受到WATCH命令和乐观锁的限制,而管道不支持事务,并且需要在使用时慎重考虑性能影响。

通过本篇博客,我们详细探讨了Redis中的事务和管道机制,了解了它们如何在实际应用中保证数据一致性和优化性能。无论是强调一致性还是追求性能,都可以根据业务需求选择合适的机制来达到最佳效果。

 

图片

 

兄弟,王者荣耀的段位排行榜是通过Redis实现的?

离谱!面试为啥都问Redis缓存?赶紧补一下

图解Dubbo,Dubbo服务治理详解

2023年再不会K8S,就要被淘汰了,手把手带你飞

10000字,图解分布式系统限流平台Sentinel

图解Nginx,系统架构演变 + Nginx反向代理与负载均衡

图解Nacos,注册中心演变 + Nacos核心功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何提高抖音直播间的人气(从15个方面为你解答)

抖音直播是一项非常受欢迎的内容创作方式&#xff0c;但是在直播过程中若是没有足够的人气&#xff0c;会让主播感到非常沮丧。如何才能提高抖音直播间的人气呢&#xff1f;本文将从15个方面为你一一解答。 一、打造独特个性的直播形象 在抖音直播中&#xff0c;每一个主播都有…

学校水电能源管理系统

随着社会的发展和经济的增长&#xff0c;学校规模逐渐扩大&#xff0c;能源消耗也不断增加&#xff0c;因此学校水电能源管理系统成为了当今智能化校园建设的重要组成部分。学校水电能源管理系统通过科技手段&#xff0c;实现对学校水电资源的全面监控和管理&#xff0c;不仅能…

OCR训练部署文档

Cuda安装 wget https://developer.download.nvidia.com/compute/cuda/11.6.0/local_installers/cuda_11.6.0_510.39.01_linux.run sh cuda_11.6.0_510.39.01_linux.run#可能会报错&#xff0c;查看/var/log/nvidia-installer.log &#xff0c;kill -9 [ID]可以解决vim ~/.bash…

FAA批准uAvionix C波段超视距飞行(BVLOS)豁免和Vantis网络

美国联邦航空管理局(FAA)于2023年9月6日在拉斯维加斯的商业无人机博览会上宣布批准uAvionix公司的豁免申请&#xff0c;允许该公司在北达科他州通过使用Vantis指挥与控制系统(C2)和检测与避障(DAA)网络&#xff0c;无需载人即可进行超视距(BVLOS)的无人机系统(UAS)操作。具体而…

视频监控/安防监控/视频云存储EasyCVR平台设备分配模块升级详解

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台支持将部署在监控现场的前端设备进行统一集中接入&#xff0c;可兼容多协议、多类型设备&#xff0c;管理员可选择任意一路或多路视频实时观看&#xff0c;视频画面支持单画面、多画面显示&#xff0c;视频窗口数量有1、4…

Origin绘制彩色光谱图

成果图 1、双击线条打开如下窗口 2、选择“图案”-》颜色-》按点-》映射-》Wavelength 3、选择颜色映射 4、单击填充-》选择加载调色板-》Rainbow-》确定 5、单击级别&#xff0c;设置成从370到780&#xff0c;右侧增量选择2&#xff08;越小&#xff0c;颜色渐变越细腻&am…

Three.js开发中遇到的常见问题总结和性能优化

关于Three.js开发中遇到的一些问题总结 1.加载外部模型文件无法在场景中显示: (1) 确保当前文件内容是否能被读取&#xff0c;在Javascript的console中查找错误&#xff0c;并确定当你调用.load()的时候&#xff0c;使用了onError回调函数来输出结果, 如果err 输出则表示当前…

sql_mode详解

文章目录 一、sql_mode作用二、查询sql_mode三、mysql8默认的mode配置&#xff08;6个默认配置&#xff09;四、常见mode详细解释mysql8默认配置了的mode&#xff08;6个&#xff09;需要自己配置的mode&#xff08;4个&#xff09; 五、设置sql_mode&#xff08;一旦设置了&am…

宠物用品做谷歌推广的三种形式

今天&#xff0c;米贸搜谷歌推广来跟大家讲讲宠物用品做谷歌推广的三种形式&#xff01; 本文中所提到的三种谷歌推广形式不仅仅适用于宠物用品行业的推广&#xff0c;也同样适用于更多的行业做好谷歌推广哟&#xff0c;如果有别的行业想要知道谷歌推广的三种推广形式&#xff…

使用Cmake编译项目从入门到精通

文章目录 1、安装2、使用CMake生成makefile2.1、项目结构介绍2.2、编写CMakeLists.txt文件2.3、优化写法12.4、给可执行程序设置路径2.5、指定头文件目录2.6、制作库以及使用 3、使用练习 cmake 的特点主要有&#xff1a; 1&#xff0c;开放源代码&#xff0c;使⽤类BSD 许可发…

网络技术二十一:ACL包过滤

ACL包过滤 ACL 定义 访问控制列表 用于数据流的匹配和筛选 常见功能 访问控制&#xff1a;ACLPacket-filter 路由控制&#xff1a;ACLRoute-policy 流量控制&#xff1a;ACLQOS 引入 ACL (Access Control List&#xff0c;访问控制列表)是用来实现数据包识别功能的 ACL可…

知名设计师推荐:2023年Pantone年度年度色彩用法

绘画巨头Pantone已宣布他们2023年的年度色彩。它是Viva品红&#xff0c;一种如此大胆和充满活力的色彩&#xff0c;我们一想到就兴奋不已。 Viva品红&#xff1a;Pantone Color Institute 2023年的年度色彩是明亮、温暖和乐观的。它也是相关的和不可避免的&#xff1b;在经历了…

浙大陈越何钦铭数据结构08-图7 公路村村通【循环和最小堆版】

题目 现有村落间道路的统计数据表中&#xff0c;列出了有可能建设成标准公路的若干条道路的成本&#xff0c;求使每个村落都有公路连通所需要的最低成本。 输入格式: 输入数据包括城镇数目正整数N&#xff08;≤1000&#xff09;和候选道路数目M&#xff08;≤3N&#xff09;…

.netcore对传输类设置区分大小

.Net Core中内置了对Json的转化与解析 可将PropertyNameCaseInsensitive false 设置为区分大小写。

socket的使用 | 服务器与客户端之间传送数据

服务器端代码&#xff1a; import java.io.*; import java.net.ServerSocket; import java.net.Socket;public class theServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(9999); // 该行代码作用&#xff1…

IGES在线查看与转换

IGES 格式最初由美国空军开发并于 1980 年发布。该格式是集成计算机辅助制造 (ICAM) 项目的产品,该项目旨在通过集成操作来降低制造成本。 IGES 文件旨在允许航空航天相关设计在不同平台上传输,同时将数据丢失降至最低。 在 IGES 格式出现之前,不同公司创建的 CAD 和计算机…

PPT怎么转换为PDF格式,收藏这两个在线工具。

PPT是一种常用的演示文稿格式&#xff0c;它可以包含丰富的动画效果和超链接&#xff0c;让你的内容更加生动和有趣。但是&#xff0c;如果你想将PPT分享给别人&#xff0c;或者在不同的设备上查看&#xff0c;你可能会遇到一些问题&#xff0c;比如&#xff1a; PPT文件太大&a…

按照xml文件和txt文件名,将对应名字的图象文件复制

按照xml文件和txt文件名&#xff0c;将对应名字的图象文件复制 需求分析解决方案 需求分析 就是已经标注了xml和txt文件&#xff0c;需要将其对应的图象文件挑选出来 解决方案 # 按照xml文件删除对应的图片 # coding: utf-8 from PIL import Image, ImageDraw, ImageFont imp…

【多线程】线程安全与线程同步

线程安全与线程同步 1.什么是线程安全问题&#xff1f; 多个线程同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全问题 取钱的线程安全问题场景&#xff1a; 两个人他们有一个共同的账户&#xff0c;余额是10万元&#xff0c;如果两个人同时来取钱&#xff0c;…

国内某头部理财服务提供商基于白鲸调度系统建立统一调度和监控运维

导读&#xff1a;国内某头部理财服务提供商成立于 2019 年&#xff0c;是股份制银行中首批获准筹建、首家获准开业、首家成立的银行理财子公司。自 2004 年推出国内首支人民币理财产品以来&#xff0c;通过投资模式的不断创新和投资管理能力的持续提升&#xff0c;引领国内银行…