认识kafka

news2024/11/16 7:38:48

认识KafKa

1.什么是KafKa:

kafka是一种高吞吐量的分布式发布订阅消息消息队列,有如下特性:

  1. 可扩展性:Kafka可以处理大规模的数据流,并支持高并发的生产和消费操作。它可以水平扩展以适应负载的增长。

  2. 持久性:Kafka将消息持久化到磁盘,允许消息在发布和消费之间进行持久存储。这使得消费者能够根据自己的节奏处理数据,并且不会因为未及时消费而丢失数据。

  3. 可靠性:Kafka通过在多个服务器上复制分区来提供容错性。如果某个服务器故障,仍然可以从其他副本读取数据。

  4. 实时处理:Kafka支持实时数据流的处理,允许应用程序实时地处理和分析数据。

  5. 生态系统:Kafka有一个丰富的生态系统,提供了各种工具和集成,如Kafka Connect用于数据导入和导出,Kafka Streams用于流处理,以及Kafka客户端库可用于多种编程语言。

*在Kafka有几个比较重要的概念:

  • broker

用于标识每一个Kafka服务,当然同一台服务器上可以开多个broker,只要他们的broker id不相同即可

  • Topic

消息主题,从逻辑上区分不同的消息类型

  • Partition

用于存放消息的队列,存放的消息都是有序的,同一主题topic可以分多个partition,如分多个partition时,同样会以如partition1存放1,3,5消息,partition2存放2,4,6消息。

  • Produce

消息生产者,生产消息,可指定向哪个topic,topic哪个分区中生成消息。

  • Consumer

消息消费者,消费消息,同一消息只能被同一个consumer group中的consumer所消费。consumer是通过offset进行标识消息被消费的位置。当然consumer的个数取决于此topic所划分的partition,如同一group中的consumer个数大于partition的个数,多出的consumer将不会处理消息。

2.kafka特征:

1.在设置一个分区的时候,生产和消费的顺序是一致的,因为只有一个分区。而设置多个分区时,消费获取分区时候是无序的,因此导致生产和消费之间顺序不一致。分区之间是无序的,分区内的消息是有序的。

2.为了解决多个分区导致的生产与消费之间的顺序不一致,我们需要向指定的分区生产以及消费,代码如下:

from confluent_kafka import Producer

# bootstrap.servers 对应的服务器地址,可以有多个mybroker
p = Producer({'bootstrap.servers': 'mybroker1,mybroker2'})

def delivery_report(err, msg):
    """ Called once for each message produced to indicate delivery result.
        Triggered by poll() or flush(). """
    if err is not None:
        print('Message delivery failed: {}'.format(err))
    else:
        print('Message delivered to {} [{}]'.format(msg.topic(), msg.partition()))

for data in some_data_source:
    # Trigger any available delivery report callbacks from previous produce() calls
    p.poll(0)

    # Asynchronously produce a message, the delivery report callback
    # will be triggered from poll() above, or flush() below, when the message has
    # been successfully delivered or failed permanently.
    # 修改此处设定partition= n, n代表几个分区
    p.produce('mytopic', data.encode('utf-8'), partition=3, callback=delivery_report)

# Wait for any outstanding messages to be delivered and delivery report
# callbacks to be triggered.
p.flush()
# =============================分割线=============================
from confluent_kafka import Consumer, KafkaError


c = Consumer({
    'bootstrap.servers': 'mybroker', # Producer中对应的bootstrap.servers 对应的服务器地址
    'group.id': 'mygroup', 
    'auto.offset.reset': 'earliest' # topic的一些配置
})

#c.subscribe(['mytopic']) # 指定消费的topic,与生产时的topic一致
# 此处修改,需要消费的分区
tp = TopicPartition("mytopic", 0, 0) # 第一个0是分区,第二个0是auto.offset.reset,不能为负数
c.assign([tp])
c.seek(tp)

while True:
    msg = c.poll(1.0)

    if msg is None:
        continue
    if msg.error():
        print("Consumer error: {}".format(msg.error()))
        continue

    print('Received message: {}'.format(msg.value().decode('utf-8')))

c.close()

3.在订阅消费模式下(c.subscribe(['mytopic'])),kafka保证每条消息在同一个Consumer Group中只会被某一个Consumer消费,就是同一个组下面的Consumer,A消费了,B就不会消费。

4.一个消费者可以同时消费多个topic

5.消费者的数量应不多于该topic分区的数量,否则多余的消费者必定无法收到消息

6.多个消费者,消费同一个分区,消费到的数据由生产的发往那个分区决定的

kafka原理

基础架构

  1. Producer :消息生产者,就是向kafka broker发消息的客户端;

  2. Consumer :消息消费者,向kafka broker取消息的客户端;

  3. Consumer Group(CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个消费组消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者**。

  4. Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。

  5. Topic :可以理解为一个队列,生产者和消费者面向的都是一个topic;

  6. Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列;

  7. Replica:副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个follower。

  8. leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。

  9. follower:每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的follower。

关于Zookeeper:

Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。

工作机制:

是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接收观察者的注册,一旦这些数据状态发生变化,Zookeeper就将负责通知已经在Zookeeper上的那些观察者做出相应的反应。

kafka工作流程及文件存储机制

Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。

topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。

文件储存机制

由于生产者生产的消息会不断追加到log文件末尾,为防止log文件过大导致数据定位效率低下,Kafka采取了分片和索引机制,将每个partition分为多个segment。每个segment对应两个文件——“.index”文件和“.log”文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic名称+分区序号。例如,first这个topic有三个分区,则其对应的文件夹为first-0,first-1,first-2。

“.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元数据指向对应数据文件中message的物理偏移地址。比如1-237

分区策略

生产者Producer

producer发送的数据封装成一个ProducerRecord对象。

(1)指明 partition 的情况下,直接将指明的值直接作为 partiton 值;

(2)没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;

(3)既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition 值,也就是常说的 round-robin 算法。

消费者consumer

一个consumer group中有多个consumer,一个 topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由哪个consumer来消费。

Kafka有两种分配策略,一是roundrobin(默认的),一是range。

数据可靠性保证

副本数据同步策略

方案

优点

缺点

半数以上完成同步,就发送ack

延迟低

选举新的leader时,容忍n台节点的故障,需要2n+1个副本

全部完成同步,才发送ack

选举新的leader时,容忍n台节点的故障,需要n+1个副本

延迟高

Kafka选择了第二种方案,原因如下:

1.同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。

2.虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。

投票的机制:

比如说3台机器,推选一个leader,每个人手里都有一票,可以投自己,发现一个人只要半数以上的票就已经可以成为leader

ISR

​ 采用第二种方案之后,设想以下情景:leader收到数据,所有follower都开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack。这个问题怎么解决呢?

​ Leader维护了一个动态的in-sync replica set (ISR),意为和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发生故障之后,就会从ISR中选举新的leader。

ack应答机制

对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功。

所以Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的配置。

acks参数配置:

acks:

0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据;

1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据

-1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会

自动提交offset

为了使我们能够专注于自己的业务逻辑,Kafka提供了自动提交offset的功能。 

自动提交offset的相关参数:

enable.auto.commit:是否开启自动提交offset功能

auto.commit.interval.ms:自动提交offset的时间间隔

producer发送消息过程

Kafka的Producer发送消息采用的是异步发送的方式。在消息发送的过程中,涉及到了两个线程——main线程和Sender线程,以及一个线程共享变量——RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker。

拦截器原理

Producer拦截器(interceptor)是在Kafka 0.10版本被引入的,主要用于实现clients端的定制化控制逻辑。

对于producer而言,interceptor使得用户在消息发送前以及producer回调逻辑前有机会对消息做一些定制化需求,比如修改消息等。同时,producer允许用户指定多个interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain)。Intercetpor的实现接口是org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:

(1)configure(configs)

获取配置信息和初始化数据时调用。

(2)onSend(ProducerRecord):

该方法封装进KafkaProducer.send方法中,即它运行在用户主线程中。Producer确保在消息被序列化以及计算分区前调用该方法。用户可以在该方法中对消息做任何操作,但最好保证不要修改消息所属的topic和分区,否则会影响目标分区的计算。

(3)onAcknowledgement(RecordMetadata, Exception):

该方法会在消息从RecordAccumulator成功发送到Kafka Broker之后,或者在发送过程中失败时调用。并且通常都是在producer回调逻辑触发之前。onAcknowledgement运行在producer的IO线程中,因此不要在该方法中放入很重的逻辑,否则会拖慢producer的消息发送效率。

(4)close:

关闭interceptor,主要用于执行一些资源清理工作

如前所述,interceptor可能被运行在多个线程中,因此在具体实现时用户需要自行确保线程安全。另外倘若指定了多个interceptor,则producer将按照指定顺序调用它们,并仅仅是捕获每个interceptor可能抛出的异常记录到错误日志中而非在向上传递。这在使用过程中要特别留意。

消息队列对比--RabbitMQ

优先选择 RabbitMQ 的条件: 高级灵活的路由规则; 消息时序控制(控制消息过期或者消息延迟); 高级的容错处理能力,在消费者更有可能处理消息不成功的情景中(瞬时或者持久); 更简单的消费者实现。 

优先选择 Kafka 的条件: 严格的消息顺序; 延长消息留存时间,包括过去消息重放的可能; 传统解决方案无法满足的高伸缩能力。

RabbitMQ

RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在不同的应用之间共享数据(跨平台跨语言)。RabbitMQ是使用Erlang语言编写,并且基于AMQP协议实现。

AMQP(Advanced Message Queuing Protocol) 高级消息队列协议:高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

AMQP中增加了Exchange和Binging的角色。生产者把消息发布到Exchange上,消息最终到达队列并被消费者接收,而Binding决定交换器的消息应该发送到哪个队列。

  • Broker : 标识消息队列服务器实体rabbitmq-server

  • v-host : Virtual Host 虚拟主机。标识一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在链接时指定,RabbitMQ默认的vhost是 /。

  • Exchange: 交换器用来接收生产者发送的消息并将这些消息路由给服务器中的队列。

    • RabbitMQ 的交换机有四种类型:fanout、direct、topic、headers。

      • Direct,完全匹配型交换机,此种类型交换机,通过RoutingKey路由键将交换机和队列进行绑定, 消息被发送到exchange时,需要根据消息的RoutingKey,来进行匹配,只将消息发送到完全匹配到此RoutingKey的队列。

      • Fanout,扇出类型交换机,此种交换机,会将消息分发给所有绑定了此交换机的队列,此时RoutingKey参数无效。

      • Topic,主题类型交换机,此种交换机与Direct类似,也是需要通过routingkey路由键进行匹配分发,区别在于Topic可以进行模糊匹配,Direct是完全匹配。Topic中,将routingkey通过"."来分为多个部分,通过如下功能字符来进行匹配:

        • "*":代表一个部分

        • "#":代表一个或多个部分

      • Headers,headers信息类型交换机,此类型交换机不通过routingkey路由键来分发消息,而是通过消息内容中的headers属性来进行匹配

  • Queue : 消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

  • Banding : 绑定,用于消息队列和交换机之间的关联。一个绑定就是基于路由键将交换机和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。

  • Channel : 信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟链接,AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入了信道的概念,以复用一条TCP连接。

  • Connection : 网络连接,比如一个TCP连接。

  • Routing key 路由键:生产者将消息发送到交换机时,会在消息头上携带一个 key,这个 key就是routing key,来指定这个消息的路由规则。等同于数据库中的where条件一样

  • Binding key 绑定键:在绑定Exchange交换机与Queue队列时,一般会指定一个binding key,生产者将消息发送给Exchange时,消息头上会携带一个routing key,当binding key与routing key相匹配时,消息将会被路由到对应的Queue中。

代码

GitHub - dpkp/kafka-python: Python client for Apache Kafka

`pip install kafka-python`

创建topic

from kafka.admin import KafkaAdminClient, NewTopic


admin_client = KafkaAdminClient(
    bootstrap_servers="localhost:9092",
    client_id='test'
)


topic_list = []
topic_list.append(NewTopic(name="topic_by_python", num_partitions=3, replication_factor=1))
admin_client.create_topics(new_topics=topic_list, validate_only=False)

消费topic

import json
from kafka import KafkaConsumer


consumer = KafkaConsumer('profile',
                         group_id='reader_2',
                         auto_offset_reset='earliest',
                         max_poll_interval_ms=600000,
                         request_timeout_ms=605000,
                         connections_max_idle_ms=700000,
                         max_poll_records=100,
                         bootstrap_servers=['localhost:9092'])
count = 0
for data in consumer:
    value = data.value
    info = json.loads(value)
    print(info)
    count += 1
    if count == 5:
        break
consumer.commit()  # 读取少量数据才需要这个

往topic生产数据

import json
import datetime
from kafka import KafkaProducer

producer = KafkaProducer(bootstrap_servers=['localhost:9092'], retries=1)
for i in range(10):
    data = {'index': i, 'name': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
    producer.send('profile', json.dumps(data).encode())
    print(data)

GitHub - confluentinc/confluent-kafka-python: Confluent's Kafka Python Client

使用文档:https://docs.confluent.io/current/clients/confluent-kafka-python/index.html

Producer

from confluent_kafka import Producer

# bootstrap.servers 对应的服务器地址,可以有多个mybroker
p = Producer({'bootstrap.servers': 'mybroker1,mybroker2'})

def delivery_report(err, msg):
    """ Called once for each message produced to indicate delivery result.
        Triggered by poll() or flush(). """
    if err is not None:
        print('Message delivery failed: {}'.format(err))
    else:
        print('Message delivered to {} [{}]'.format(msg.topic(), msg.partition()))

for data in some_data_source:
    # Trigger any available delivery report callbacks from previous produce() calls
    p.poll(0)

    # Asynchronously produce a message, the delivery report callback
    # will be triggered from poll() above, or flush() below, when the message has
    # been successfully delivered or failed permanently.
    p.produce('mytopic', data.encode('utf-8'), callback=delivery_report)

# Wait for any outstanding messages to be delivered and delivery report
# callbacks to be triggered.
p.flush()

Consumer


from confluent_kafka import Consumer, KafkaError

c = Consumer({
    'bootstrap.servers': 'mybroker', # Producer中对应的bootstrap.servers 对应的服务器地址
    'group.id': 'mygroup', 
    'auto.offset.reset': 'earliest' # topic的一些配置
})

c.subscribe(['mytopic']) # 指定消费的topic,与生产时的topic一致

while True:
    msg = c.poll(1.0)
    if msg is None:
        continue
    if msg.error():
        print("Consumer error: {}".format(msg.error()))
        continue

    print('Received message: {}'.format(msg.value().decode('utf-8')))
c.close()

kafka在数据流处理中的作用

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

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

相关文章

从无到有制作docker镜像、容器详细步骤

1、编写一个Dockerfile文件,内容如下 # 基础镜像jdk,jdk里包含里操作系统 FROM openjdk:8u282-jdk# 工作目录,也就是容器里目录 WORKDIR /home/prq/# 添加ppp目录下的文件到容器/home/prq/里 ADD ./ppp /home/prq/# 暴露端口8080 EXPOSE 8080# 启动脚本…

AdaM: An Adaptive Fine-Grained Scheme for Distributed Metadata Management——泛读论文

ICPP 2019 Paper 分布式元数据论文汇总 问题 为了同时解决元数据局部性和元数据服务器的负载均衡。 现有方法缺陷 基于哈希的方法:zFS [16],CalvinFS [21],DROP [24],AngleCut [8] 静态子树划分:HDFS [6], NFS [14…

【Golang】IEEE754标准二进制字符串转为浮点类型

IEEE754介绍 IEEE 754是一种标准,用于表示和执行浮点数运算的方法。在这个标准中,单精度浮点数使用32位二进制表示,分为三个部分:符号位、指数位和尾数位。 符号位(s)用一个位来表示数的正负,0表示正数,1表…

LInux初学之路linux的磁盘分区/远程控制/以及关闭图形界面/查看个人身份

虚拟机磁盘分配 hostname -I 查看ip地址 ssh root虚拟就ip 远程连接 win10之后才有 远程控制重新启动 reboot xshell 使用(个人和家庭版 免费去官方下载) init 3 关闭界面 减小内存使用空间 init 5 回复图形界面 runlevel显示的是状态 此时和上…

代码随想录二刷 |二叉树 | 二叉搜索树的最小绝对差

代码随想录二刷 |二叉树 | 二叉搜索树的最小绝对差 题目描述解题思路 & 代码实现递归法迭代法 题目描述 530.二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。 示例&#…

VR全景技术如何应用在城市发展,助力城市宣传展示

引言: 随着科技的不断发展,VR全景技术正逐渐渗透到各行各业,其中较为广泛的应用之一便是城市展示。那么VR全景技术如何运用在城市展示领域,这项技术给城市发展带来了哪些好处? 一. VR全景技术简介 1.什么是VR全景技术…

Java十大经典算法——贪心算法

算法概念: 贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法;贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解),但…

拯救者y9000p安装linux、windows双系统。

首先需要准备启动盘 我用的是Win32DiskImager来做的。资源使用的是ubuntu-20.04.6-desktop-amd64.iso。别用低版本,失败很多次之后的教训。 磁盘管理-磁盘分区-右键-压缩卷 这边分区出来之后,不要分配。安装时候会自动分配的。 重启之后F2进去BIOS设置…

计算机系统(软考版)----计算机系统基础知识、基本单位与进制(1)

文章目录 计算机系统基础知识一 硬件组成二 CPU功能三 CPU组成运算器控制器寄存器组 练习题(答案为加粗部分) 计算机基本单位与进制一 计算机基本单位二 进制1 概述2 进制转换3 进制加减 练习题(答案为加粗部分) 计算机系统基础知…

Blazor中使用impress.js

impress.js是什么? 你想在浏览器中做PPT吗?比如在做某些类似于PPT自动翻页,局部放大之类,炫酷无比。 官方示例直接放到Blazor中是不可用的。几经尝试,用以下方法可以实现。 (写文不易,请点赞、…

MySql前言

🎥 个人主页:Dikz12🔥个人专栏:MySql📕格言:那些在暗处执拗生长的花,终有一日会馥郁传香欢迎大家👍点赞✍评论⭐收藏 目录 数据库有哪些软件?? Mysql MySql数…

数据科学竞赛平台推荐

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。 🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心&…

叠加文件夹内所有png文件 python

→ import os import cv2 import matplotlib.pyplot as pltPATH "./1" #文件路径 i 0 #子文件夹路径 img10 for parent, dirs, files in os.walk(PATH):for file in files:if not file.endswith(.png):continueimg cv2.imread(os.path.join(parent, file))if i0:i…

mysql表的约束问题

目录 1. 表的约束问题: 主键约束: 案例: 非空约束 唯一约束: 默认值约束: 案例: 2.表的结构 前提:接上一张博客内容经行操作 1. 表的约束问题: 用来保证数据插入的安全性、完整性、正确性 主健,外键,唯一,默认值,非空,检查 主键…

TMC2226步进电机驱动---学习记录

基于TMC2226数据手册的学习 主要内容介绍: Package Outline TMC2226 手册中引脚解释(按照手册表格顺序) 了解每个引脚是接什么的,之后看原理图 (借用立创广场kirito的原理图,后期换个) 以前的疑…

202404读书笔记|《只愿你被这世界温柔相待》——我跌落于生活的荆棘,高傲,机敏,桀骜不驯

202404读书笔记|《只愿你被这世界温柔相待》——我跌落于生活的荆棘,高傲,机敏,桀骜不驯 CHAPTER1 只为途中与你相见CHAPTER2 只要有爱就有痛CHAPTER3 为自己的心安一个家CHAPTER4 让往事随风 《只愿你被这世界温柔相待》作者雪莱等&#xff…

基于AI视频智能分析技术的周界安全防范方案

一、背景分析 随着科技的不断进步,AI视频智能检测技术已经成为周界安全防范的一种重要手段。A智能分析网关V4基于深度学习和计算机视觉技术,可以通过多种AI周界防范算法,实时、精准地监测人员入侵行为,及时发现异常情况并发出警报…

【开源】基于JAVA语言的民宿预定管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用例设计2.2 功能设计2.2.1 租客角色2.2.2 房主角色2.2.3 系统管理员角色 三、系统展示四、核心代码4.1 查询民宿4.2 新增民宿4.3 新增民宿评价4.4 查询留言4.5 新增民宿订单 五、免责说明 一、摘要 1.1 项目介绍 基于…

vue3打包后页面空白解决方法

vue3打包后页面空白解决方法 问题解决方法 问题 最近写一个小项目 没有打包的时候一切正常 技术栈用的vue3 vite 我用的是npm创建的项目 npm init vuelatest问题一 :打包后页面空白,什么都没有 问题二:刷新页面后找不到资源 把url的inde…

C++ 之LeetCode刷题记录(九)

😄😊😆😃😄😊😆😃 开始cpp刷题之旅,多学多练,尽力而为。 先易后难,先刷简单的。 58. 最后一个单词的长度 给你一个字符串 s,由若干…