京东生产环境十万并发秒杀系统三高架构

文章目录

  • 三高——高并发、高可用、高可扩展
    • 用数据库乐观锁解决超卖
    • 阿里巴巴:为了提升数据库性能,对数据库的源码级别做了改造——在DB内部实现内存队列,一次性接收很多的请求,一次性更新。
    • 京东:redis,mq,也有用缓存的
    • redis集群架构部署
    • redis集群架构的数据倾斜怎么解决?
    • 热点商品问题——怎么解决并发?
    • MQ丢消息怎么解决?
    • MQ消息积压怎么解决?
    • 解决MQ下单消息重复消费幂等机制
    • Redis集群崩溃时如何保证秒杀系统高可用
      • 第一步:设计高可用的Redis集群
        • 1. Redis主从复制
        • 2. Redis Sentinel
        • 3. Redis Cluster
      • 第二步:秒杀系统的高可用设计
        • 1. 分布式架构
        • 2. 限流和排队
        • 3. 异步处理
      • 第三步:应对Redis集群崩溃
        • 1. 降级处理
        • 2. 数据同步
    • Redis主从切换导致库存同步异常以及超卖问题
    • MQ集群崩溃时如何保证秒杀系统高可用
    • 秒杀链路中Redis与MQ如何保证事务一致性

1、高并发场景秒杀抢购超卖Bug实战重现
2、阿里巴巴内部高并发秒杀下单方案首次揭秘
3、基于Redis与MQ实现秒杀下单架构
4、十万订单每秒热点数据架构优化实践
5、秒杀下单MQ如何保证不丢消息
6、解决MQ下单消息重复消费幂等机制详解
7、线上MQ百万秒杀订单积压优化实战
8、Redis集群崩溃时如何保证秒杀系统高可用
9、Redis主从切换导致库存同步异常以及超卖问题
10、MQ集群崩溃时如何保证秒杀系统高可用
11、秒杀链路中Redis与MQ如何保证事务一致性

三高——高并发、高可用、高可扩展

秒杀系统一般单独部署,省的影响其他服务,
在这里插入图片描述

在这里插入图片描述
这样的秒杀,在高并发情况下会产生超卖的情况,怎么办?

用数据库乐观锁解决超卖

在这里插入图片描述
数据库上千的并发已经是极限了,虽然没加分布式锁(分布式锁性能更差劲),那希望性能继续提升怎么办?

阿里巴巴:为了提升数据库性能,对数据库的源码级别做了改造——在DB内部实现内存队列,一次性接收很多的请求,一次性更新。

一般公司是没能力改这个的。

京东:redis,mq,也有用缓存的

先看一个用redis简单实现的
在这里插入图片描述
异步下单,下单的时候没有操作数据库,性能就提高了,先给用户返回抢购成功,前面加一个转圈圈的过程,后面的交给MQ,前段可以定时的往后端发送是否下单成功,直到查询到下单成功在跳转到支付页面。
在这里插入图片描述
但现在的方案,每秒能支撑十万的并发吗?——显然不行。
redis理论上每秒十万的请求(一般只有查询,等等等条件下)。

redis集群架构部署

在这里插入图片描述
redis集群,数据是分片存储的——有哈希分片算法
一个redis读写混合并发,撑死也就两三万。
那我们把秒杀商品均匀的分配到不同的redis节点上,理论上,只要节点足够多,可以抗住十万的并发,但是实际上,万一分片的全都到一个节点上了,就不行了
在这里插入图片描述

redis集群架构的数据倾斜怎么解决?

  1. 预热商品缓存的时候我们是清楚的,万一在预热的时候发生数据倾斜了,就通过一些命令把一部分数据迁移到其他节点上去,尽可能均匀分配。
  2. HashTag,在key前面加上HashTag,这样也可以解决数据倾斜

但是还有问题——热点商品也会导致某一个节点并发过量

热点商品问题——怎么解决并发?

做缓存预热的时候就应该把这个商品拆分开
在这里插入图片描述
可以做数据的分片,是对一个商品的库存做分片。

再看看这样的秒杀系统,还有什么问题?
在这里插入图片描述

MQ丢消息怎么解决?

肯定有丢消息的可能,不同的MQ有不同的方案

简单点的方案,在发MQ消息之前,存一份到消息发送表,等处理完成后在回去修改消息发送表。

在这里插入图片描述
虽然不至于丢,但是毕竟操作数据库了,并发肯定不高。
针对不同的MQ做对应的MQ消息丢失的方案

MQ消息积压怎么解决?

消息积压会导致前端一直转圈圈(哈哈哈),但是等十来分钟你会等吗?

插DB慢,我们可以插redis,那查的话怎么查询?如果查DB找不到,就找Redis
如果收到message的发送时间和当前的处理时间太长了,快速的插入到redis。这是临时的处理方案,最终后台还是要同步到DB的。

如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

你看这问法,其实本质针对的场景,都是说,可能你的消费端出了问题,不消费了;或者消费的速度极其慢。接着就坑爹了,可能你的消息队列集群的磁盘都快写满了,都没人消费,这个时候怎么办?或者是这整个就积压了几个小时,你这个时候怎么办?或者是你积压的时间太长了,导致比如 RabbitMQ 设置了消息过期时间后就没了怎么办?

所以就这事儿,其实线上挺常见的,一般不出,一出就是大 case。一般常见于,举个例子,消费端每次消费之后要写 mysql,结果 mysql 挂了,消费端 hang 那儿了,不动了;或者是消费端出了个什么岔子,导致消费速度极其慢。
问题剖析
关于这个事儿,我们一个一个来梳理吧,先假设一个场景,我们现在消费端出故障了,然后大量消息在 mq 里积压,现在出事故了,慌了。
大量消息在 mq 里积压了几个小时了还没解决

几千万条数据在 MQ 里积压了七八个小时,从下午 4 点多,积压到了晚上 11 点多。这个是我们真实遇到过的一个场景,确实是线上故障了,这个时候要不然就是修复 consumer 的问题,让它恢复消费速度,然后傻傻的等待几个小时消费完毕。这个肯定不能在面试的时候说吧。

一个消费者一秒是 1000 条,一秒 3 个消费者是 3000 条,一分钟就是 18 万条。所以如果你积压了几百万到上千万的数据,即使消费者恢复了,也需要大概 1 小时的时间才能恢复过来。

一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下:

  • 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉。
  • 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
  • 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
  • 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
  • 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。

mq 中的消息过期失效了

假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢。

这个情况下,就不是说要增加 consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上 12 点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。

假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。

mq 都快写满了
如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。

对于 RocketMQ,官方针对消息积压问题,提供了解决方案。

1. 提高消费并行度
大部分消息消费行为都属于 IO 密集型,即可能是操作数据库,或者调用 RPC,这类消费行为的消费速度在于后端数据库或者外系统的吞吐量,通过增加消费并行度,可以提高总的消费吞吐量,但是并行度增加到一定程度,反而会下降。所以,应用必须要设置合理的并行度。如下有几种修改消费并行度的方法:

同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度(需要注意的是超过订阅队列数的 Consumer 实例无效)。可以通过加机器,或者在已有机器启动多个进程的方式。提高单个 Consumer 的消费并行线程,通过修改参数 consumeThreadMin、consumeThreadMax 实现。
2. 批量方式消费
某些业务流程如果支持批量方式消费,则可以很大程度上提高消费吞吐量,例如订单扣款类应用,一次处理一个订单耗时 1 s,一次处理 10 个订单可能也只耗时 2 s,这样即可大幅度提高消费的吞吐量,通过设置 consumer 的 consumeMessageBatchMaxSize 返个参数,默认是 1,即一次只消费一条消息,例如设置为 N,那么每次消费的消息数小于等于 N。

3. 跳过非重要消息
发生消息堆积时,如果消费速度一直追不上发送速度,如果业务对数据要求不高的话,可以选择丢弃不重要的消息。例如,当某个队列的消息数堆积到 100000 条以上,则尝试丢弃部分或全部消息,这样就可以快速追上发送消息的速度。示例代码如下:

public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,ConsumeConcurrentlyContext context) {long offset = msgs.get(0).getQueueOffset();String maxOffset =msgs.get(0).getProperty(Message.PROPERTY_MAX_OFFSET);long diff = Long.parseLong(maxOffset) - offset;if (diff > 100000) {// TODO 消息堆积情况的特殊处理return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}// TODO 正常消费过程return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}

4. 优化每条消息消费过程
举例如下,某条消息的消费过程如下:

•根据消息从 DB 查询【数据 1】•根据消息从 DB 查询【数据 2】•复杂的业务计算•向 DB 插入【数据 3】•向 DB 插入【数据 4】

这条消息的消费过程中有 4 次与 DB 的 交互,如果按照每次 5ms 计算,那么总共耗时 20ms,假设业务计算耗时 5ms,那么总过耗时 25ms,所以如果能把 4 次 DB 交互优化为 2 次,那么总耗时就可以优化到 15ms,即总体性能提高了 40%。所以应用如果对时延敏感的话,可以把 DB 部署在 SSD 硬盘,相比于 SCSI 磁盘,前者的 RT 会小很多。

解决MQ下单消息重复消费幂等机制

发消息重复了,重试一次,但实际上成功了,又发了一次,

重复消费会带来的问题呢?如果消费者的业务逻辑是执行一个查询的逻辑,那么无论消费几次,这对于业务来说是没有太大的影响的,但如果消费者的业务逻辑是向数据库中插入一条数据,那么重复消费将会导致至少插入两条相同的数据,自然导致了数据的异常。

那么幂等是什么意思呢?幂等(idempotent、idempotence)实际上是一个数学与计算机学概念,在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,通俗点说就是:同样的参数或者数据去调用同一个接口,无论重复调用多少次,总能保证数据的正确性,不能出错,这就是接口的幂等性。这里“数据的正确性”和具体的业务相关,不同的业务,对于幂等性的定义是不一样的。

基于幂等性的要求,我们需要改造业务处理逻辑,使得在重复消息的情况下也不会影响最终的结果。怎么改造呢?这得结合具体的业务来考虑:

  1. 如果一个业务是只读业务,或者是更新的业务,那么多次读取或者多次更新相同的数据基本上都没什么问题。
  2. 如果业务需要插入数据,但是插入的数据中有唯一key能够区分(比如订单id,或者生产者生成的token),那么业务逻辑就可以变成在插入前先查询这个唯一key是否在数据库中,如果消费方的业务表不需要存储这个key,那么消费方也可以单独建立一张唯一key表,插入唯一key表和插入业务表的sql逻辑一定要都在一个事务中,在插入前判断这个唯一key是否在数据库的唯一key表中,如果存在说明此前已经成功消费了这条消息,不再消费,否则就是没有成功消费,继续消费。
  3. 如果业务需要插入数据,但是插入的数据中没有唯一key能够区分,这种是无法完全避免因为多条重复的消息或者一条消息多次重复消费带来的问题。因此最好是让发送消息的同事向消息内容中添加一个唯一的字段,即使消费者方的业务不需要也没关系,因为这样就能的防止重复的消息和重复消费了。
  4. 上面通过数据库的方式来防止重复消费的都属于“强校验”类型,会一定程度上影响数据库性能,通常涉及到金钱的都需要强校验,如果不需要强校验,那么使用Redis来代替也行,比如生产者将id或者token作为key存入Redis,消费者消费时先判断是否存在id或者token,如果存在则消费,消费完毕之后消除key。很多的业务都不需要强校验,比如获取登陆短信验证码的时候,多发送两条,或者发送失败都没关系,我们都遇到过。
    上面的都是通用的办法,但处理重复消费的问题,始终要根据具体业务来考虑自己的解决办法,比如我们公司有很多监听一张表的binlog日志然后将操作同步到另一张表上的场景,这种情况下,某些消费者直接将原始表的id作为同步表的id,这样插入的时候,如果id重复肯定是插入不了的,天然的就保证了消息的幂等性。但有时候,同步的表是使用的自己的自增id,此时就需要在插入之前通过其他唯一的业务字段判断此数据是否已被消费过,如果被消费过,则不执行插入。

Redis集群崩溃时如何保证秒杀系统高可用

第一步:设计高可用的Redis集群

在构建高可用的秒杀系统之前,我们需要首先确保Redis集群本身是高可用的。这可以通过以下几种方式来实现:

1. Redis主从复制

使用Redis的主从复制机制,将主节点的数据复制到多个从节点上。当主节点发生故障时,可以立即切换到一个从节点,确保数据的持久性和可用性。

# Redis主从配置示例
# 主节点配置
bind 127.0.0.1
port 6379
# 从节点配置
replicaof 127.0.0.1 6379
2. Redis Sentinel

Redis Sentinel是Redis官方提供的高可用解决方案,它可以监控Redis集群中的主从节点,并在主节点故障时自动选举新的主节点。

# Redis Sentinel配置示例
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
3. Redis Cluster

Redis Cluster是Redis的分布式解决方案,它将数据分片存储在多个节点上,并提供了自动数据迁移和故障转移功能。

# Redis Cluster配置示例
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-slave-validity-factor 10

选择适合您需求的高可用方案,并确保Redis集群的稳定性和可用性。

第二步:秒杀系统的高可用设计

一旦Redis集群高可用性得到保证,接下来我们将关注秒杀系统本身的高可用性设计。

1. 分布式架构

将秒杀系统设计成分布式架构,将请求分散到多个节点上。这可以通过负载均衡器(如Nginx或HAProxy)来实现,确保请求不会集中在单一节点上。

# Nginx负载均衡配置示例
http {upstream backend {server app1.example.com;server app2.example.com;server app3.example.com;}server {listen 80;location / {proxy_pass http://backend;}}
}
2. 限流和排队

在秒杀活动开始时,可能会涌入大量请求。为了避免系统过载,可以实施请求限流和排队机制。使用Redis的有序集合(Sorted Set)来维护请求的排队顺序,并使用计数器来限制每秒的请求数量。

import redis# 连接到Redis集群
redis_client = redis.StrictRedis(host='redis-cluster-ip', port=6379, db=0)def handle_seckill_request(user_id):# 检查请求是否超过限流阈值if redis_client.incr('seckill_request_count') <= MAX_REQUEST_PER_SECOND:# 将用户加入秒杀队列redis_client.zadd('seckill_queue', {user_id: time.time()})else:# 返回请求失败信息return "秒杀请求过多,请稍后重试"
3. 异步处理

将秒杀请求的处理过程异步化,将请求加入消息队列(如RabbitMQ或Kafka)中,然后由后台任务处理器来执行秒杀操作。这可以降低系统负载,提高响应速度。

# 将秒杀请求加入消息队列
def enqueue_seckill_request(user_id):message_queue.push({'user_id': user_id})# 后台任务处理器
def process_seckill_request():while True:request = message_queue.pop()if request:handle_seckill_request(request['user_id'])

第三步:应对Redis集群崩溃

即使我们已经采取了多种措施来确保Redis集群的高可用性,但仍然有可能发生Redis集群的崩溃。在这种情况下,我们需要采取措施来保证秒杀系统的高可用性。

1. 降级处理

当Redis集群崩溃时,可以采取降级处理策略,将秒杀系统切换到一个临时的、基于数据库的模式。这可以通过配置文件来实现,将数据库作为备用数据源。
比如:rocksDB可以记录操作的流水日志

# 配置文件中的Redis切换策略
if redis_cluster_available:cache = RedisCache()
else:cache = DatabaseCache()
2. 数据同步

在Redis集群恢复之后,需要将数据库中的数据同步回Redis集群,以确保数据的一致性。可以使用数据同步工具或自定义脚本来实现这一过程。

# 数据同步脚本示例
def sync_data_to_redis():database_data = fetch_data_from_database()for key, value in database_data.items():redis_client.set(key, value)

Redis主从切换导致库存同步异常以及超卖问题

Redis的主从是异步同步的,redis的主从异步同步,假设某商品,主节点是100,从节点也是100,这是主节点减一成99,还没来得及同步,但这时候99的主节点挂了,另一个是100的节点成主节点了。在这里插入图片描述
一般互联网公司不解决,但面试官非要问你,要解决怎么办?
——红锁
直接修改redis源码,让主从同步,不仅难度太大,而且性能下降
那么怎么办,我们不搞从节点,全部搞成主节点。

在这里插入图片描述

MQ集群崩溃时如何保证秒杀系统高可用

在这里插入图片描述

秒杀链路中Redis与MQ如何保证事务一致性

在当今互联网时代,秒杀活动成为了各大电商平台吸引用户的重要手段。然而,秒杀活动的高并发场景对系统的性能和稳定性提出了巨大的挑战。为了保证秒杀链路中的事务一致性,我们需要借助Redis和MQ这两个强大的工具。本文将详细介绍Redis与MQ如何保证事务一致性,并给出相应的代码demo。

一、秒杀链路中的事务一致性问题

在秒杀活动中,用户在短时间内涌入系统,同时抢购同一商品,这就会导致高并发的读写请求。而在传统的数据库事务中,由于数据库的读写锁机制,会导致性能瓶颈,无法满足秒杀活动的高并发需求。因此,我们需要寻找一种更高效的解决方案。

二、Redis的应用

Redis是一种高性能的NoSQL数据库,其特点是快速、可持久化、支持多种数据结构等。在秒杀链路中,我们可以利用Redis的原子操作和高速读写特性来保证事务的一致性。

商品库存的管理
在秒杀活动中,商品的库存是一个重要的指标。我们可以将每个商品的库存数量存储在Redis中,并利用Redis的原子操作实现库存的减少和增加。
示例代码:

# 初始化商品库存
redis.set('product:stock', 100)# 减少库存
def decrease_stock():stock = redis.get('product:stock')if stock > 0:redis.decr('product:stock')return Trueelse:return False# 增加库存
def increase_stock():redis.incr('product:stock')

1.用户购买记录的管理
为了防止用户重复购买同一商品,我们需要记录用户的购买信息。同样地,我们可以利用Redis的原子操作和高速读写特性来管理用户的购买记录。
示例代码:

# 记录用户购买记录
def record_purchase(user_id, product_id):redis.sadd('user:%s:purchases' % user_id, product_id)# 检查用户是否已购买过该商品
def check_purchase(user_id, product_id):return redis.sismember('user:%s:purchases' % user_id, product_id)

三、MQ的应用

MQ(消息队列)是一种高效的异步通信机制,可以实现不同服务之间的解耦和削峰填谷。在秒杀链路中,我们可以利用MQ来异步处理订单的生成和支付等操作,从而保证事务的一致性。

订单生成
当用户成功秒杀到商品后,我们可以将生成订单的操作放入MQ中异步处理。这样可以减轻系统的压力,提高响应速度。
示例代码:

# 订单生成
def generate_order(user_id, product_id):# 生成订单逻辑...# 将订单信息放入MQ中mq.push('order', order_info)

2.订单支付
在用户生成订单后,我们可以将订单支付的操作放入MQ中异步处理。这样可以保证订单的支付和库存的减少是原子操作,从而保证事务的一致性。
示例代码:

# 订单支付
def pay_order(order_id):# 订单支付逻辑...# 将支付结果放入MQ中mq.push('pay', pay_result)

四、保证事务一致性的实现

通过Redis和MQ的应用,我们可以实现秒杀链路中的事务一致性。具体的实现步骤如下:

用户请求秒杀商品时,先检查用户是否已购买过该商品,如果已购买,则返回秒杀失败;
如果用户未购买过该商品,则先检查商品的库存是否大于0,如果大于0,则继续执行下一步;
从Redis中减少商品的库存,并记录用户的购买记录;
将生成订单的操作放入MQ中异步处理;
在订单生成的消费者中,处理订单的生成和支付操作,保证订单的支付和库存的减少是原子操作;
在订单支付的消费者中,处理订单的支付结果。
通过以上步骤,我们可以保证秒杀链路中的事务一致性,有效应对高并发场景下的性能和稳定性问题。

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

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

相关文章

无线通信基础

这里写目录标题 通信概述什么是无线通信无线通信电磁波 通信概述 什么是无线通信 无线通信 : 是指利用电磁波信号可以在自由空间中传播的特性进行信息交换的一种通信方式 无线通信的关键技术包括调制技术、解调技术、信道编码技术、信号处理技术、天线技术等。这些技术的不断…

医药垃圾分类管理系统|基于SSM医药垃圾分类管理系统的系统设计与实现(源码+数据库+文档)

医药垃圾分类管理系统 目录 基于SSM医药垃圾分类管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统登录模块 2管理员模块实现 3用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…

《十九》Qt Http协议及实战

前言 本篇文章来给大家讲解QT中的Http协议&#xff0c;Http协议主要用于网络中数据的请求和响应&#xff0c;那么这篇文章将给大家讲解一下这个协议。 一、HTTP概述 HTTP&#xff08;超文本传输协议&#xff09;是互联网上应用最为广泛的协议之一&#xff0c;它定义了客户端…

LM4562NA 直插DIP8双运放 音频hifi运算放大器

LM4562NA是一款高性能音频运算放大器&#xff0c;其应用领域主要集中在音频和声音处理方面&#xff0c;包括但不限于&#xff1a; 1. 专业录音设备&#xff1a;在录音棚、广播电台和电视台等专业环境中&#xff0c;用于信号放大和处理&#xff0c;确保高质量的声音录制和传输…

北邮22级信通院DSP:实验三(1):FFT变换、IFFT变换(附每步8点变换蝶形图)保姆级讲解+用C++程序实现复数域的FFT变换和IFFT变换

北邮22信通一枚~ 跟随课程进度更新北邮信通院DSP的笔记、代码和文章&#xff0c;欢迎关注~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院DSP_青山入墨雨如画的博客-CSDN博客 目录 一、预备知识 1.1 FFT算法 1.2.1由DFT到FFT 1.2.2 基2时域抽选算法 …

并发编程之阻塞队列BlockingQueue实战及其原理分析

1. 阻塞队列介绍 1.1 队列 是限定在一端进行插入&#xff0c;另一端进行删除的特殊线性表。 先进先出(FIFO)线性表。 允许出队的一端称为队头&#xff0c;允许入队的一端称为队尾。

使用开放式用户通信连接两台西门子S71200plc

步骤1.在项目中创建两台PLC。 步骤2.分别设置两个PLC的参数。 plc1 plc2 步骤3.对两个plc进行组态 步骤4.在plc1和plc2中各自创建DB块&#xff0c;用于通信。 须在块的属性中取消优化块的访问选项。 plc1 plc2 步骤5.往plc1的main块中编写代码。 步骤6.往plc2的main块中编写…

Markdown 精简教程(胎教级教程)

文章目录 一、关于 Markdown1. 什么是 Markdown&#xff1f;2. 为什么要用 Markdown&#xff1f;3. 怎么用 Markdown&#xff1f;&#xff08;编辑软件&#xff09; 二、标题1. 常用标题写法2. 可选标题写法3. 自定义标题 ID4. 注意事项 三、段落四、换行五、字体选项1. 粗体2.…

15.计算机网络

1.物理层的互联设备 中继器 和 集线器 2.集线器可以看做特殊的多路中继器 集线器 不可以做到自动寻址的功能 3.数据链路层 网桥 和 交换机 4.交换机是多端口网桥 5.网络层 路由器 6.应用层 网关 7.广播域 网络层 可以形成多个广播域 冲突域 网络层数据链路层 可以形成多个冲突域…

网络安全--红队资源大合集

目录 相关资源列表 攻防测试手册 内网安全文档 学习靶场 工具包集合 内网安全文档 学习手册相关资源 产品设计文档 版本管理平台漏洞收集 相关工具拓展插件 Kali 环境下拓展插件 Nessus 相关工具拓展插件 Awvs 相关工具拓展插件 红队攻击的生命周期&#xff0c;…

第三节课,前端

一、参考链接&#xff1b; 总 知识星球 | 深度连接铁杆粉丝&#xff0c;运营高品质社群&#xff0c;知识变现的工具 分 2022-03-18 星球直播笔记-用户中心&#xff08;下&#xff09; 语雀 二、登录 2.1登录网址 2.2前端页面修改 2.1 页面修改 2.2 页脚的超链接 网址&am…

Linux初识

1.操作系统的那点事 &#xff08;1&#xff09;结论&#xff1a;操作系统是作软硬件管理的软件&#xff1b; &#xff08;2&#xff09;计算机是操作系统&#xff0c;设备驱动&#xff0c;硬件三个相互结合发挥作用的&#xff0c;操作系统是用来管理硬件的&#xff0c;常见的…

简易录制视频做3D高斯

系统环境 ubuntu20 &#xff0c;cuda11.8&#xff0c;anaconda配置好了3D高斯的环境。 具体参考3D高斯环境配置&#xff1a;https://blog.csdn.net/Son_of_the_Bronx/article/details/138527329?spm1001.2014.3001.5501 colmap安装&#xff1a;https://blog.csdn.net/Son_of…

嵌入式linux学习第三天汇编语言点灯

嵌入式linux学习第三天汇编语言点灯 今天学习如何在linux板子上点灯。 I.MX6U GPIO 详解 我们发现I.MX6U GPIO是分为两类的&#xff0c;&#xff1a;SNVS 域的和通用的。在讨论i.MX6U或类似的复杂微处理器时&#xff0c;了解其GPIO&#xff08;通用输入输出&#xff09;引脚…

八.吊打面试官系列-Tomcat优化-深入源码剖析Tomcat如何打破双亲委派

前言 上篇文章《Tomcat优化-深入Tomcat底层原理》我们从宏观上分析了一下Tomcat的顶层架构以及核心组件的执行流程。本篇文章我们从源码角度来分析Tomcat的类加载机制&#xff0c;且看它是如何打破JVM的ClassLoader双亲委派的 Tomcat ClassLoader 初始化 Tomcat的启动类是在…

华为eNSP小型园区网络配置(下)

→跟着大佬学习的b站直通车&#xff0c;感谢大佬← →华为eNSP小型园区网络配置&#xff08;上&#xff09;← 目标1&#xff1a;telnet配置 R1 # interface GigabitEthernet0/0/2ip address 100.1.1.2 255.255.255.0 # user-interface vty 0 4authentication-mode aaa # aaa…

英语新概念2-回译法-lesson12

第一次翻译 &#xff08;稀巴烂&#xff09; Our neiborhood,Capitain Charles Alison,will sail from P. We will ______ in the _. He will sit in his small boat, Topsail,Topsail is a famous boat. It has been across the A many times. Alison will sail at 8 o’cloc…

05-06 周一 Shell工程目录划分和开发最佳实践

05-06 周一 Shell工程目录划分和开发最佳实践 时间版本修改人描述2024年5月6日10:34:13V0.1宋全恒新建文档2024年5月6日11:07:12V1.0宋全恒完成 简介 之前楼主曾经完成过一个shell工程的开发&#xff0c;记得当时项目名称叫做campus-shell&#xff0c;主要是用来一键完成多个模…

【信息安全管理与评估】某年“信息安全管理与评估”第二阶段:Windows应急响应例题

文章目录 1、提交攻击者的IP地址&#xff1b;2、识别攻击者使用的操作系统&#xff1b;3、找出攻击者资产收集所使用的平台&#xff1b;4、提交攻击者目录扫描所使用的工具名称&#xff1b;5、提交攻击者首次攻击成功的时间&#xff0c;格式&#xff1a;DD /MM/YY:HH:MM:SS&…

SpringBoot中HandlerInterceptor拦截器的构建详细教程

作用范围&#xff1a;拦截器主要作用于Spring MVC的DispatcherServlet处理流程中&#xff0c;针对进入Controller层的请求进行拦截处理。它基于Java的反射机制&#xff0c;通过AOP&#xff08;面向切面编程&#xff09;的思想实现&#xff0c;因此它能够访问Spring容器中的Bean…