微服务系统面经之二: 以秒杀系统为例

news2024/11/14 10:30:06

16 微服务与集群部署

16.1 一个微服务一般会采用集群部署吗?

对于一个微服务是否采用集群部署,这完全取决于具体的业务需求和系统规模。如果一个微服务的访问压力较大,或者需要提供高可用性,那么采用集群部署是一种常见的策略。通过集群部署,可以在一定程度上提高服务的可用性和容错能力,因为当某个节点发生故障时,其他的节点可以继续提供服务。同时,通过负载均衡技术,可以将请求分散到各个节点,提高系统的处理能力。

16.2 为什么每一个微服务都可以提供读写服务?而不是像raft集群那样部署,只能leader节点提供读写能力,其他节点保证一致性和可用性

这是因为他们的读写的数据库是同一个,所以一致性保证是由独立部署的分布式数据库测提供。

在微服务架构中,每个微服务都可以提供读写服务,这主要是因为微服务架构的设计原则之一就是服务的自治。每个微服务都应该能够独立地处理请求,而不需要依赖其他的服务。对于数据存储,**一般来说,每个微服务都会有自己独立的数据库,以避免跨服务的数据依赖。**这样,即使是写操作,也可以由任何一个微服务节点来处理。当然,对于数据的一致性保证,通常是由数据库本身来提供。

对于你提到的Raft集群,它是一种强一致性的复制协议,通常用于实现分布式系统的状态机复制。在Raft中,只有Leader节点才能处理客户端的请求,这主要是为了保证数据的一致性。但是在微服务架构中,由于每个服务都有自己的数据库,所以一致性问题主要是由数据库来处理的,而微服务只需要关注如何处理业务逻辑即可。

16.3 每个微服务都会有自己独立的数据库,但是一个微服务的所有实例共享这个数据库对吧

对的,一个微服务的所有实例通常会共享一个数据库。这是因为在微服务架构中,每个微服务都应该是自治的,这意味着它们应该拥有自己的数据存储,并且能够独立地处理请求。

例如,假设你有一个订单服务,你可能会有多个实例来处理高并发的订单请求。尽管你有多个订单服务实例,但是他们会共享同一个订单数据库。

这样的设计可以让微服务自己管理和控制对自己数据的访问,以及如何实现业务逻辑,这有助于微服务的独立发展和快速迭代。同时,由于微服务的所有实例都访问同一个数据库,所以他们能够看到同一份数据,保证了数据的一致性。

然而,也需要注意,这样的设计可能会引发一些问题,比如数据库的并发访问控制,数据的一致性和隔离性问题等,这就需要我们在实际的系统设计和开发中去妥善处理。

17 请求的有序性问题(重点)

17.1 单机下的请求有序性问题秒杀及其解决方案

17.1.1 同一个应用先后发出的两个http请求,到达服务端的顺序可能发出的顺序不一致吧?不一致的话会有什么危害(当时暑期实习面滴滴的一个问题,现在才明白怎么回事)

是的,同一个应用发送的两个HTTP请求可能在到达服务器时的顺序和发送时的顺序不同。这是由于网络延迟、服务器的处理速度等因素都可能导致这种情况发生。如果你的应用逻辑依赖于请求的发送顺序,那么这可能会导致问题。

例如,如果一个请求是用来更新数据,另一个请求是用来读取这个数据,那么如果读取请求先于更新请求到达,那么就会读取到旧的数据。或者,如果你有两个请求,一个是用来创建一个资源,另一个是用来删除这个资源,如果删除请求先到达,那么就会出现无法删除一个不存在的资源的错误。

这种情况下,一种可能的解决方案是在服务器端实现某种形式的请求序列化,即按照一定的规则(例如请求的时间戳、或者一些业务相关的顺序)来处理请求。但是,这可能会增加服务器的复杂性和处理延迟。

另一种解决方案是让客户端处理这种情况。例如,如果客户端知道一个请求依赖于另一个请求的结果,那么它可以等待第一个请求完成后再发送第二个请求。或者,客户端可以包含一些信息在请求中,让服务器知道请求的相关性和顺序。

这个问题在分布式系统中是非常常见的,被称为"请求的有序性问题"。处理这个问题通常需要一些复杂的设计和编程技巧。

17.1.2 方案一:在客户端保证请求的有序性(业务层面保证)

以用户在秒杀场景中先下单后支付为例,可以在支付之前查询redis缓存或者mysql数据库判断订单是否已经完成,如果完成才允许进行支付操作,否则拒绝。

17.1.3 方案二:利用消息队列FIFO特性保证服务端消费请求的顺序一致性

为每个用户维护一个消息队列,所有该用户发出的请求都首先进入这个队列,然后由服务器按照队列的顺序(FIFO)来处理这些请求。以kafka为例,kafka为每一个用户新建一个topic,且保证这个topic的分区数量(等同于队列数量)和消费者数量一一对应,客户端在发送消息到队列时要指定具体的分区,对应的下单/支付(这俩必须是绑定在一个一起)消费者必须消费这个指定的分区,那么就能保证消费的顺序性

但是这里又存在一个问题,如何保证生产中发送的消息到达队列中的顺序和发送顺序是一致的呢?

答:利用停止-等待协议,产生同步阻塞,生产者在向消息到队列后会阻塞住,直到收到了队列所在服务器的确认才会继续发送下一个消息

但是这样设置完后,需要进行消息去重操作,同时还要保证消息的幂等性,这里会借鉴tcp协议在保证幂等性上的做法,在发送端,每次发送一条消息都会将序列号+1(但是重发的请求公用初始时分配的序列号),kafka端本身会有一个从客户端id到序列号的映射,存储的是最近一次该客户端成功发送的消息序列号,也就是说重发的请求序列号必然小于等于这个map中存储该客户端的序列号,通过对比就可以知道这个请求是否是旧的。

但是这种方案一般不推荐,因为众所周知停等协议是非常慢的,这样做只会浪费kafka的消费速度

大家可以参考这篇文章:Kafka如何做到发送端和接收端的顺序一致性?

17.1.4 真正的解决方案一:业务层硬编码保证有序

从业务层再做重排,典型的就是支付之前先查表判断是否抢购并且下单成功

17.1.4 真正的解决方案二:使用kafka

(1)正经解决就是不在需要严格保序的场景里用kafka,比如扣减库存操作,哪一个用户请求先扣都无所谓
(2)(待定)还有一种是使用kafka的分区特性,将互相依赖的消息放入到同一个消费分区的消费队列中,这个分区内的消息是顺序消费的,只需要保证放入分区队列中的顺序是符合依赖就行

17.2 多机下的请求有序性

17.2.1 一个微服务通常以集群方式部署,每一个实例都能提供全量的功能,如果下单请求打到了实例A,但是支付请求打到了实例B,最后B比A先到达数据库,这种顺序不一致如何保证呢?

实例B在支付之前查询redis缓存或者mysql数据库判断订单是否已经完成,如果完成才允许支付操作,否则fail掉,随后再重发,但是这里就需要保证支付操作的幂等性(多次请求的结果和第一次执行的结果状态相同),参考上面提到的tcp幂等性保证即可。

17.3 面试场景(重点)

17.3.4 秒杀场景中的消息公平性定义

消息的公平性在不同的上下文中可能有不同的含义。在一些情况下,它可能指的是保证消息被处理的顺序与它们到达的顺序相同(先来后到,比如AQS中的公平锁)。在其他情况下,它可能指的是保证每个发送者都有公平的机会让他们的消息被处理,而不是让某些先到的发送者的消息被优先处理。

在秒杀场景中,消息的公平性通常更关注后者,即确保所有的用户都有公平的机会参与秒杀,而不是让请求先到的用户有更高的机会。这通常通过随机选取、每人限购、等概率抽取等手段来实现。

至于先来后到的问题,由于网络延迟和服务器处理速度的差异,严格的先来后到在实际的网络环境中很难实现。同时,如果只优先处理请求先到的用户,那么有可能导致网络条件好或者手速快的用户总是抢先一步,不利于公平性。

17.3.5 面试官:消息的公平性如何保证,即保证每一个请求都有机会获取到商品秒杀的权利?即回答一下如何确认这1000w条里面有哪一百条才能得到商品数据?

答:以下四种方法中,1和2只能保证先到先得得公平性,不适用秒杀场景,3和4适合秒杀场景

理想的情况下,我们希望能完全公平地处理所有用户的请求。但在实际操作中,为了保证系统的高并发性能,一般的实践是在处理大量请求时只能保证一定的公平性,即只能保证大部分请求都有机会得到处理,而不能保证完全按照请求的顺序进行处理。

为了尽可能保证公平性,我们可以采取以下的一些策略:

  1. 预减库存:在用户请求秒杀时,我们可以在Redis等高速缓存中进行预减库存操作。如果预减成功,再将用户的请求发送到消息队列中,等待后续处理。这种方式可以有效防止库存超卖,但并不能完全保证公平性。

  2. 使用有序队列:如果我们想要更好的公平性,可以考虑使用有序的消息队列,比如Kafka。这样,我们可以按照用户请求的顺序进行处理。然而,这种方式可能会降低系统的并发处理能力。

  3. 分批处理:我们还可以考虑将用户的请求分批处理。例如,我们可以每秒处理一定数量的请求,然后在这些请求中随机选择一部分进行处理。这种方式既可以保证一定的公平性,又可以保证系统的并发处理能力。

  4. (这个可能真正回答了如何确认1000w条)使用抽签系统:对于超高并发的场景,我们甚至可以考虑使用抽签系统。在用户请求秒杀时,我们可以让用户参与一个抽签,只有抽中的用户才有资格进行秒杀。这种方式可以有效防止库存超卖,并且在一定程度上保证了公平性。

需要注意的是,上述的各种策略都只能在一定程度上保证公平性,并不能保证完全的公平。因为在高并发的环境下,完全的公平性往往意味着较低的性能。因此,在实际的系统设计中,我们需要在公平性和性能之间找到一个合适的平衡点。

17.3.6 如果使用抽签系统(可以单独做一个微服务,或者在本地生成也可以),如何设计这个系统呢,给出一个可行的高校方法,会用到什么算法

设计一个抽签系统,通常可以根据以下步骤进行:

  1. **用户报名:**当用户点击秒杀按钮时,不直接进行秒杀操作,而是标记该用户为参与抽签。这可以通过在数据库中为每个用户创建一条记录来实现,记录中包含用户ID和商品ID等信息。

  2. **生成抽签池:**在秒杀开始之前,从所有报名的用户中抽取一部分用户作为参与抽签的用户,形成一个抽签池。生成抽签池的方法可以有多种,例如随机抽取,或者根据用户的购买历史、信用等级等因素进行筛选。

  3. **进行抽签:**在秒杀开始时,从抽签池中随机选取一部分用户作为中签用户,这些用户有权进行秒杀操作。进行抽签的方式也可以有多种,例如可以使用简单的随机算法,或者使用更复杂的加权随机算法,对信用等级高的用户给予更高的中签概率。

  4. **通知中签用户:**抽签结束后,需要将抽签结果通知给所有参与抽签的用户。对于中签用户,可以直接发送一个包含秒杀链接的通知,用户点击链接后可以直接进行秒杀操作。

这个系统的关键在于如何进行抽签。最简单的方式是使用随机算法,例如可以使用Java的Random类生成随机数,然后根据随机数决定是否选取某个用户。对于更复杂的场景,例如需要根据用户的信用等级等因素进行抽签,可以使用加权随机算法,根据每个用户的权重生成随机数,权重大的用户生成的随机数范围更大,因此中签的概率也更高。

注意,以上只是一个抽签系统的基本设计方案,具体实现时可能需要考虑更多的细节,例如如何处理网络延迟、如何保证抽签的公平性、如何处理用户重复报名等问题。

17.3.7 介绍一下加权随机法的实现方式以及java代码

  1. 加权随机法的实现方式

加权随机法是一种根据权重进行随机选择的方法。具体实现如下:

  • 首先,我们需要一个列表来存储所有的用户和他们的权重。
  • 然后,我们计算所有用户权重的总和。
  • 然后,我们生成一个0到总权重之间的随机数。
  • 最后,我们从列表的第一个元素开始,累加每个元素的权重,当累加的权重大于或等于随机数时,就返回该元素。

这个算法的时间复杂度为O(n),空间复杂度也为O(n)。

以下是该方法的Java实现:

public class WeightedRandom {
    private static class Node {
        int weight;
        String user;
        
        Node(String user, int weight) {
            this.weight = weight;
            this.user = user;
        }
    }
    
    private List<Node> nodeList = new ArrayList<>();
    private int totalWeight = 0;
    
    public void addUser(String user, int weight) {
        nodeList.add(new Node(user, weight));
        totalWeight += weight;
    }
    
    public String getRandomUser() {
        int randomWeight = new Random().nextInt(totalWeight);
        int weightSum = 0;
        for (Node node : nodeList) {
            weightSum += node.weight;
            if (randomWeight < weightSum)
                return node.user;
        }
        return null;
    }
}

在这段代码中,我们首先定义了一个内部类Node来存储用户和权重,然后在主类WeightedRandom中定义了一个列表nodeList来存储所有的Node,和一个变量totalWeight来存储所有权重的总和。然后,我们定义了两个方法,addUser用于添加用户,getRandomUser用于根据权重随机选择一个用户。

17.3.8 使用抽签方式后,是否需要使用redis预减库存

使用抽签方式后,流量可以直接打到消息队列,但是使用redis预减库存仍然是一个好的做法,它可以进一步提升系统的响应速度,并且减少数据库的压力。

17.3.9 抽签系统在高并发环境下的考虑

在高并发环境下,抽签系统需要考虑并发控制和性能优化。例如,当大量用户同时请求抽签时,可能会导致系统的负载过高。为了解决这个问题,可以使用限流算法,例如漏桶算法或者令牌桶算法,来控制请求的并发数;每次只放一批请求过来去抽签

17.3.10 如何对没有抽中的人进行去重操作(防止它持续性点击)

对于没有抽中的用户,可以在数据库或者缓存中为每个用户创建一个标记,标记用户是否已经参与过抽签。然后在用户请求抽签时,首先检查这个标记,如果用户已经参与过抽签,就直接返回一个提示信息,告诉用户不要重复点击。这种方法的效率很高,可以有效防止用户持续性点击。

18关于超卖问题

我写的一篇关于超卖问题的解决方案

18.1 秒杀系统中的超卖问题解决方案

**超卖问题主要是由于并发情况下,系统无法保证库存扣减的原子性。**解决超卖问题的常见方式如下:

  • 乐观锁:乐观锁实际上是一种思想,即假设系统在大部分时间里不会发生并发冲突,所以只在真正写入数据时才会检查是否存在冲突。在秒杀系统中,可以在数据库中为商品设定一个版本号(或时间戳),每次更新库存时,都对比版本号(或时间戳),只有当版本号(或时间戳)符合预期时,才进行更新,并将版本号(或时间戳)加一。

  • 悲观锁:相比于乐观锁的乐观假设,悲观锁假设每次去读数据都会发生并发冲突,所以在每次读数据的时候都会上锁,确保在读写数据时不会被其他线程影响。

  • 使用分布式锁:例如Redis的SETNX命令或者Zookeeper、etcd等分布式协调服务。

  • 数据库行级锁:例如MySQL InnoDB引擎的行级锁等。

  • 队列串行化:将请求放入消息队列,一个一个的处理。

18.2 关于使用etcd分布式锁的方案

可以采用etcd分布式锁来解决秒杀系统中的超卖问题。在请求打到数据库之前,每个请求都尝试获取锁,只有成功获取锁的请求才能去数据库扣减库存。这样可以保证对库存扣减的操作是串行的,从而避免了超卖的问题。

  • 优点:可以有效避免超卖问题,保证数据的一致性。

  • 缺点:并发性能可能会下降。因为所有的请求都需要尝试获取锁,如果请求量非常大,可能会导致大量的请求在等待获取锁,从而增加了系统的响应时间。同时,对于分布式锁的使用,也需要考虑锁的生命周期管理,例如避免死锁、锁超时自动释放等问题。

一种常见的优化方案是,结合缓存、消息队列和数据库三者,首先在缓存中进行库存检查和预减库存,然后将请求放入消息队列,最后由消费者线程去数据库中扣减真正的库存。这种方案既能避免超卖问题,又能提高系统的并发处理能力。

19 关于秒杀的微服务系统的多级限流问题

19.1 微服务系统的多级限流措施?各级之间的限流关系是怎么样的?

nginx,api网关,rpc框架以及接口本身都可能会做限流,这几种限流器允许同时存在

19.2 nginx的限流器是如何实现的

19.3 api-gateway如何实现限流的,以zuul为例

19.4 dubbo如何实现服务限流和熔断

dubbo如何实现服务限流和熔断

19.5 自定义的限流器是如何实现限流的?

一般常见的有三种算法,滑动窗口、令牌桶给和漏桶,从中选取一个作为限流算法,然后配合AOP的前置通知或者注解和redis,实现对不同粒度、不同接口以及不同用户的限流。

19.3 先流的粒度和方式方法以及各种方法的优劣权衡

可以查看下面这篇文章的第19点
系统设计类题目汇总二

20 秒杀模块的数据表如何设计的

20.1 为了避免影响正常的购物流量,为正在秒杀的活动单独创建了一套秒杀表,包括秒杀商品表、秒杀订单表,为什么?

秒杀活动(Flash Sales)通常会导致巨大的流量涌入,这对任何电子商务网站或应用来说都是一次巨大的压力测试。设计一套专门针对秒杀活动的数据库表结构有多个好处:

1. 系统性能

秒杀活动需要非常快速的读写操作。通过创建单独的秒杀表,可以对这些表进行特定的优化,例如:高速缓存、分区等,以提高性能。

2. 数据隔离

正常购物流量和秒杀流量通常有不同的业务规则和数据需求。通过隔离这些数据,你可以减少复杂性,并使得常规操作不受秒杀活动的影响。

3. 可扩展性

单独的秒杀表意味着你可以更容易地将秒杀相关的数据和逻辑迁移到独立的服务或数据库,以提高系统整体的可扩展性。

4. 简化问题排查

出现问题时,拥有专门的秒杀表可以更容易地定位和解决问题,因为你只需要关注一个相对较小和专门化的数据集。

5. 提高安全性

由于秒杀活动容易受到各种攻击(例如,刷单,机器人抢购等),单独的数据表结构使得可以更方便地实施特定的安全措施。

示例数据表设计

下面是一个非常基础的示例,用于描述可能的秒杀商品表和秒杀订单表:

秒杀商品表 (FlashSaleProducts)

  • id: 主键
  • product_name: 商品名称
  • original_price: 原价
  • flash_sale_price: 秒杀价
  • quantity_available: 可用数量
  • start_time: 秒杀开始时间
  • end_time: 秒杀结束时间

秒杀订单表 (FlashSaleOrders)

  • id: 主键
  • user_id: 用户ID
  • flash_sale_product_id: 秒杀商品ID(外键)
  • quantity: 购买数量
  • order_time: 下单时间
  • status: 订单状态(例如,完成、取消、失败等)

这样的设计提供了一个基础框架,可以根据特定需求进行进一步的定制和优化。

20.2 秒杀商品和订单表与普通的商品订单表是什么关系?

秒杀商品和订单表与普通的商品和订单表在业务逻辑和用途上有一定的关联性,但通常会被设计为相对独立的数据结构。下面是他们之间可能的关系:

20.2.1 数据模型

  1. 共享商品数据:秒杀商品通常是普通商品表(Products)中的子集。在这种情况下,秒杀商品表(FlashSaleProducts)可能有一个字段,如 original_product_id,作为外键指向普通商品表的相应条目。

    FlashSaleProducts
    - original_product_id (Foreign Key -> Products.id)
    
  2. 共享用户数据:同样,秒杀订单表(FlashSaleOrders)和普通订单表(Orders)可能共享同一个用户表(Users)。

    FlashSaleOrders
    - user_id (Foreign Key -> Users.id)
    
    Orders
    - user_id (Foreign Key -> Users.id)
    

20.2.2 数据流

  1. 商品信息同步:如果一个商品同时出现在普通商品表和秒杀商品表中,那么需要确保这两个表中的商品信息(如价格、库存等)能够同步或至少保持一致。

  2. 订单转换:在某些情况下,一个开始作为秒杀订单的订单可能最终会转换为普通订单,或者反过来。

20.2.3 数据隔离

尽管有一定的关联性,但通常推荐将秒杀相关的数据表与普通购物流程的数据表分开。这样做有助于:

  1. 性能优化:针对秒杀场景进行特定的性能优化。
  2. 降低复杂性:减少在一个单一的表中处理多种业务逻辑的复杂性。
  3. 安全性:秒杀活动通常需要额外的安全措施,如防刷单、防机器人等。

总体来说,尽管秒杀商品和订单表可能与普通的商品和订单表有一定的数据和业务逻辑重叠,但将它们设计为独立的表通常是更可取的。这样可以更灵活地应对不同的性能、安全和业务需求。

20.3 所以秒杀中的商品库存扣减了之后,还需要将这个库存的减少数量在商品表中也减一遍嘛?同理秒杀订单也需要同步到普通的订单表中嘛?

20.3.1 商品库存

  1. 同步方式: 如果秒杀商品和普通商品共享同一库存,那么在秒杀期间对商品库存的任何扣减确实需要在普通的商品表中也进行相应的扣减。

  2. 独立库存: 另一种方式是为秒杀活动分配独立的库存。这种情况下,在秒杀表中的库存扣减不会影响到普通商品表的库存。

选择哪种方式取决于业务需求。共享库存更符合现实世界的物流,但可能增加系统复杂性。独立库存则更容易管理,但可能与实际物流状态有偏差。

20.3.2 订单同步

  1. 不同步: 秒杀订单和普通订单可以被视为完全独立的实体,各自维护在各自的表中。这样做可以简化处理逻辑,并允许针对秒杀订单进行特定的优化。

  2. 同步至普通订单表: 在秒杀活动结束后,或者在订单状态发生变更(例如,从’未支付’变为’已支付’)时,可以选择将秒杀订单同步到普通订单表中。这样做可以统一订单处理逻辑,但会增加系统复杂性。

  3. 标记或状态字段: 也可以在普通的订单表中加入字段,以标识是否为秒杀订单。这样,普通订单和秒杀订单就可以在同一张表中管理,但这也会增加查询和管理的复杂性。

是否需要同步取决于你的具体需求,例如,是否需要在一个统一的界面中管理所有类型的订单,或者是否有必要将所有订单数据集成到一个单一的分析系统中。

总体来说,如何处理库存和订单同步是一个业务决策,取决于你的具体需求和约束。不论选择哪种方式,都需要确保系统的一致性、可扩展性和性能。

20.4 下面是我创建的几张相关表

1 普通商品表和秒杀商品表
在这里插入图片描述
在这里插入图片描述
2 普通订单表和秒杀订单表

在这里插入图片描述
在这里插入图片描述

21 JMeter

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

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

相关文章

社区供稿 | FaceChain 开源项目原理解析

一、背景说明 各类 AI 写真软件由于其精准的个人形象精美的生成效果引爆了朋友圈传播&#xff0c;证件照满足了用户刚需&#xff0c;古装照等风格照满足了用户“美照”的需求。 FaceChain 是一个可以用来打造个人数字形象的深度学习模型工具。用户仅需要提供最低三张照片即可获…

十五、pikachu之CSRF

文章目录 一、CSRF概述二、CSRF实战2.1 CSRF(get)2.2 CSRF之token 一、CSRF概述 Cross-site request forgery 简称为“CSRF”&#xff0c;在CSRF的攻击场景中攻击者会伪造一个请求&#xff08;这个请求一般是一个链接&#xff09;&#xff0c;然后欺骗目标用户进行点击&#xf…

对标 GPT-4?科大讯飞刘庆峰:华为GPU技术能力已与英伟达持平

科大讯飞创始人、董事长刘庆峰在亚布力中国企业家论坛第十九届夏季高峰会上透露了关于自家大模型进展的一些新内容。刘庆峰认为&#xff0c;中国在人工智能领域的算法并没有问题&#xff0c;但是算力方面似乎一直被英伟达所限制。 以往的“百模大战”中&#xff0c;训练大型模型…

mysql下载

网址 MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2、选择MSI进行安装 3、这里我选择离线安装 4、这里我选择直接下载 5、等待下载安装即可

改变癌症诊断!梯度提升方法可准确预测癌症患者的生存风险!

一、引言 癌症是全球范围内一种严重的疾病&#xff0c;对人类健康造成了巨大的威胁。据世界卫生组织统计&#xff0c;癌症是全球首要死因之一&#xff0c;每年有数百万人因癌症而丧生 [1]。然而&#xff0c;早期的癌症诊断和治疗非常重要&#xff0c;可以显著提高患者的存活率和…

滑动窗口系列4-Leetcode322题零钱兑换-限制张数-暴力递归到动态规划再到滑动窗口

这个题目是Leecode322的变种&#xff0c;322原题如下&#xff1a; 我们这里的变化是把硬币变成可以重复的&#xff0c;并且只有coins数组中给出的这么多的金币&#xff0c;也就是说有数量限制&#xff1a; package dataStructure.leecode.practice;import java.util.Arrays; i…

ChatGPT癌症治疗“困难重重”,真假混讲难辨真假,准确有待提高

近年来&#xff0c;人工智能在医疗领域的应用逐渐增多&#xff0c;其中自然语言处理模型如ChatGPT在提供医疗建议和信息方面引起了广泛关注。然而&#xff0c;最新的研究表明&#xff0c;尽管ChatGPT在许多领域取得了成功&#xff0c;但它在癌症治疗方案上的准确性仍有待提高。…

华为OD机试 - 完全数计算(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、Java算法源码五、效果展示六、纵览全局 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多&…

Lalamu-免费视频口型同步工具,创建属于你自己的虚拟数字人

什么是Lalamu? Lalamu 是一款视频口型同步应用程序。该应用程序由 Lalamu Entertainment 开发&#xff0c;允许用户对视频中的任何面孔进行口型同步。无论是人物、人体模型、书籍封面、艺术品、演员、婴儿、蜡像&#xff0c;甚至银行账单上的面孔&#xff0c;Lalamu 都可以让…

FreeSWITCH 1.10.10 简单图形化界面4 - 腾讯云NAT设置

FreeSWITCH 1.10.10 简单图形化界面4 - 腾讯云NAT设置 0、 界面预览1、 查看IP地址2、 修改协议配置3、 开放腾讯云防火墙4、 设置ACL5、 设置协议中ACL&#xff0c;让PBX匹配内外网6、 重新加载SIP模块7、 查看状态8、 测试一下 0、 界面预览 http://myfs.f3322.net:8020/ 用…

尝试自主打造一个有限状态机(二)

前言 上一篇文章我们从理论角度去探索了状态机的定义、组成、作用以及设计&#xff0c;对状态机有了一个基本的认识&#xff0c;这么做有利于我们更好地去分析基于实际应用的状态机&#xff0c;以及在自主设计状态机时也能更加地有条不紊。本篇文章将从状态机的实际应用出发&am…

AI项目四:基于mediapipe的钢铁侠操作(虚拟拖拽)

若该文为原创文章&#xff0c;转载请注明原文出处。 一、介绍 在B站看到使用CVZone进行虚拟物体拖放&#xff0c;模仿钢铁侠电影里的程序操作&#xff01;_哔哩哔哩_bilibili 是使用CVZone方式实现的&#xff0c;代码教程来源https://www.computervision.zone,感兴趣可以测试…

MathType7.4mac最新版本数学公式编辑器安装教程

MathType7.4中文版是一款功能强大且易于使用的公式编辑器。该软件可与word软件配合使用&#xff0c;有效提高了教学人员的工作效率&#xff0c;避免了一些数学符号和公式无法在word中输入的麻烦。新版MathType7.4启用了全新的LOGO&#xff0c;带来了更多对数学符号和公式的支持…

全国自考02325《计算机系统结构》历年真题试卷及答案 年份:202304

2023 年4 月高等教育自学考试全国统一命题考试 计算机系统结构试题答案及评分参考 &#xff08;课程代码 02325) 一、选择题&#xff1a;本大题共 10小题&#xff0c;每小题1分 1.D 2.B 3.D 4.A 5.B 6.C 7.D 8.D 9. A 10.C 二、填空题&#xff1a;本大题共 10小题&#xff…

如何加入微信群?微信加群教程,如何加更多的群聊?

微信群是人们交流互动的重要平台之一&#xff0c;加入合适的微信群可以拓宽人脉、获取信息和分享经验。下面小编将分享三个方法&#xff0c;帮助你轻松加入心仪的微信群。 方法一&#xff1a;扫描二维码加入 很多微信群会设置专属的二维码&#xff0c;方便他人加入。当你得到某…

Linux操作系统--shell编程(条件判断)

(1).基本的语法 test condition [ condition ] 注意condition前后要有空格;在使用该种表达式的时候,条件非空即为 true,[ hello ]返回 true,[ ] 返回 false。我们可以通过echo $?来判断上一次执行的情况来判断真假(0真1假)。

详解预处理

全文目录 前言预定义符号#define 定义标识符常量#define 定义宏#define 替换规则# 宏参数转换字符串## 宏参数拼接带有副作用的宏参数 宏与函数的对比#undef 移出宏定义命令行定义条件编译#include 文件包含头文件的包含方式头文件的重复包含 前言 前面我们学习了程序的编译和…

【C语言基础】源文件与头文件详解

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Office Tool Plus 使用与激活

Office Tool Plus 一个强大且实用的 Office 部署工具。 可以免费激活使用office各种版本 体验了一下&#xff0c;觉得很不错&#xff0c;我介绍一下我使用的方式&#xff1a; 1.安装软件 访问官网&#xff1a;Office Tool Plus 选择ZIP的包&#xff0c;下载后解压&#xff0c…

Huggingface托管机器学习模型及API提供

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我想在我的网络和移动应用程序中使用机器学习模型&#xff0c;但要做到这一点&#xff0c;我必须在某个地方托管我的机器学习应用程序。 托管预先训练的 ML 模型称为推理。 我只想添加一些 Python ML 代码并快速获得 REST…