当前位置: 首页 > news >正文

Kafka 生产者应用解析

目录

1、生产者消息发送流程

1.1、发送原理

2、异步发送 API

2.1、普通异步发送

2.2、带回调函数的异步发送

3、同步发送 API

4、生产者分区

4.1、分区的优势

4.2、生产者发送消息的分区策略

示例1:将数据发往指定 partition 

示例2:有 key 的情况下将数据发送到Kafka

4.3、自定义分区器

5、生产者提高吞吐量

6、数据可靠性

7、数据去重

1、幂等性

8、生产者事务

1、事务原理

2、使用事务

9、数据的有序

注:示例代码使用的语言是Python

1、生产者消息发送流程

1.1、发送原理

  • 在消息发送的过程中,涉及到了两个线程——main 线程和 Sender 线程。在 main 线程 中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给 RecordAccumulator, Sender 线程不断从 RecordAccumulator 中拉取消息发送到 Kafka Broker。

参数说明:

  • batch size:只有数据积累到batch.size之后,sender才会发送数据。默认16K
  • linger.ms:如果数据迟迟未达到batch.size,sender等待linger.ms设置的时间到了之后在发送是数据。单位ms,默认值为0ms,表示没有延迟。
  • acks:
    • 0:生产者发送过来的数据不需要等待应答,异步发送。
    • 1:生产者发送过来的数据,需要等待Leader收到后应该。
    • -1(all):生产者发送过来的数据,Leader和ISR(In-Sync Replicas)队列里面所有的节点收齐数据后应答。注:-1与all等价

2、异步发送 API

2.1、普通异步发送

示例:创建 Kafka 生产者,采用异步的方式发送到 Kafka Broker

from kafka3 import KafkaProducerdef producer(topic: str, msg: str, partition=0):""":function: 生产者,生产数据:param topic: 写入数据所在的topic:param msg: 写入的数据:param partition: 写入数据所在的分区:return:"""print("开始生产数据......")# 初始化生产者对象,bootstrap_servers参数传入kafka集群# 将acks的值设为0,acks=0,此方式也是异步的方式,但是生产环境中不会这样使用,因为存在数据丢失的风险# producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"], acks=0)producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, value=bytes(msg, 'utf-8'), partition=partition)producer.close()if __name__ == '__main__':msg = "this is profucer01"topic = "first"producer(topic, msg)

2.2、带回调函数的异步发送

  • 回调函数会在 producer 收到 ack 时调用,为异步调用,该方法有两个参数,分别是元 数据信息(RecordMetadata)和异常信息(Exception),如果 Exception 为 null,说明消息发 送成功,如果 Exception 不为 null,说明消息发送失败。
  • 注意:消息发送失败会自动重试,不需要在回调函数中手动重试。
"""
带回调函数的异步发送
回调函数会在 producer 收到 ack 时调用,为异步调用,该方法有两个参数,分别是元数据信息(RecordMetadata)和异常信息(Exception),
如果 Exception 为 null,说明消息发送成功,如果 Exception 不为 null,说明消息发送失败。
"""
from kafka3 import KafkaProducerdef producer(topic: str, msg: str, partition=0):""":function: 生产者,生产数据:param topic: 写入数据所在的topic:param msg: 写入的数据:param partition: 写入数据所在的分区:return:"""print("开始生产数据......")# 定义发送成功的回调函数def on_send_success(record_metadata):print("消息成功发送到主题:", record_metadata.topic)print("分区:", record_metadata.partition)print("偏移量:", record_metadata.offset)# 定义发送失败的回调函数def on_send_error(excp):print("发送消息时出现错误:", excp)# 可以根据实际情况执行一些错误处理逻辑# 初始化生产者对象,bootstrap_servers参数传入kafka集群producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8producer.send(topic=topic, value=bytes(msg, 'utf-8'), partition=partition).add_callback(on_send_success).add_errback(on_send_error)producer.close()

3、同步发送 API

  • 只需在异步发送的基础上,再调用一下 get()方法即可。或者将acks的值设为all,acks="all",此方式也是同步的方式。
from kafka3 import KafkaProducerdef producer(topic: str, msg: str, partition=0):""":function: 生产者,生产数据:param topic: 写入数据所在的topic:param msg: 写入的数据:param partition: 写入数据所在的分区:return:"""print("开始生产数据......")# 初始化生产者对象,bootstrap_servers参数传入kafka集群# 将acks的值设为all,acks="all",此方式也是同步的方式.# producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"], acks="all")producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, value=bytes(msg, 'utf-8'), partition=partition)# 等待 Future 返回结果,设置超时时间为10秒future.get(timeout=10)producer.close()

4、生产者分区

4.1、分区的优势

  • 1、便于合理使用存储资源,每个Partition在一个Broker上存储,可以把海量的数据按照分区切割成一 块一块数据存储在多台Broker上。合理控制分区的任务,可以实现负载均衡的效果。
  • 2、提高并行度,生产者可以以分区为单位发送数据;消费者可以以分区为单位进行消费数据。

4.2、生产者发送消息的分区策略

  • 1、如果不指定分区,会使用默认分区策略。默认分区策略如下:
    • 如果key存在的情况下,将key的hash值与topic的partition进行取余得到partition值
    • 如果key不存在的情况下,会随机选择一个分区

  • 2、如果指明了分区,那么将会把数据发送到指定分区

示例1:将数据发往指定 partition 

  • 将所有数据发往分区 0 中。

# 指定分区
def producer_01(topic: str, msg: str, partition=0):""":function: 指定分区:param topic: 写入数据所在的topic:param msg: 写入的数据:param partition: 写入数据所在的分区:return:"""# 初始化生产者对象,bootstrap_servers参数传入kafka集群producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, value=bytes(msg, 'utf-8'), partition=partition)try:# 等待消息发送完成sendResult = future.get(timeout=10)print(f"消息: {msg}\n所在的分区: {sendResult.partition}\n偏移量为: {sendResult.offset}\n")# 关闭生产producer.close()except KafkaError as e:print(f"消息: {msg} 发送失败\n失败信息为: {e}\n")msg = "this is partition"
topic = "first"
for i in range(5):producer_01(topic, msg+str(i))

示例2:有 key 的情况下将数据发送到Kafka

  • 没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取 余得到 partition 值。
# 没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值。
def producer_02(topic: str, msg: str, key: str):""":function: 指定分区:param topic: 写入数据所在的topic:param msg: 写入的数据:param key: 发送消息的key值:return:"""# 初始化生产者对象,bootstrap_servers参数传入kafka集群producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, key=bytes(key, 'utf-8'), value=bytes(msg, 'utf-8'))try:# 等待消息发送完成sendResult = future.get(timeout=10)print(f"消息: {msg}\n所在的分区: {sendResult.partition}\n偏移量为: {sendResult.offset}\n")# 关闭生产producer.close()except KafkaError as e:print(f"消息: {msg} 发送失败\n失败信息为: {e}\n")msg = "this is partition"
topic = "first"
key = "a"
for i in range(5):producer_02(topic, msg+str(i), key)

4.3、自定义分区器

  • 可以根据实际需要,自定义实现分区器。
  • 示例:自定义分区 发送过来的数据中如果包含 hello,就发往 0 号分区,不包含 hello,就发往 1 号分区。
# 自定义分区 发送过来的数据中如果包含 hello,就发往 0 号分区,不包含 hello,就发往 1 号分区。
def producer_03(topic: str, msg: str):""":function: 自定义分区:param topic: 写入数据所在的topic:param msg: 写入的数据:return:"""# 自定义分区器def my_partitioner(msg):if "hello" in str(msg):return 0else:return 1# 初始化生产者对象,bootstrap_servers参数传入kafka集群producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"])# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, value=bytes(msg, 'utf-8'), partition=my_partitioner(msg))try:# 等待消息发送完成sendResult = future.get(timeout=10)print(f"消息: {msg}\n所在的分区: {sendResult.partition}\n偏移量为: {sendResult.offset}\n")# 关闭生产producer.close()except KafkaError as e:print(f"消息: {msg} 发送失败\n失败信息为: {e}\n")msg = "hello this is partition"
msg1 = "this is partition"

5、生产者提高吞吐量

  • 实际工作中,会根据实际的情况动态的调整生产者的吞吐量以适应实际需求,调整吞吐量主要是通过调整以下参数实现:
    • batch.size:批次大小,默认16k
    • linger.ms:等待时间,修改为5-100ms
    • compression.type:压缩snappy
    • RecordAccumulator:缓冲区大小,默认32m,修改为64m
"""
生产者提高吞吐量1、linger.ms:等待时间,修改为5-100ms2、compression.type:压缩snappy3、RecordAccumulator:缓冲区大小,修改为64m
"""
from kafka3 import KafkaProducer
from kafka3.errors import KafkaErrordef producer(topic: str, msg: str):""":function: 生产者,生产数据:param topic: 写入数据所在的topic:param msg: 写入的数据:return:"""# 初始化生产者对象,bootstrap_servers参数传入kafka集群producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"],linger_ms=5, # linger_ms设置为5mscompression_type="snappy", # 设置压缩类型为snappybuffer_memory=64*1024*1024 # 设置缓冲区大小为64MB)# 将发送消息转换成bytes类型,编码使用utf-8future = producer.send(topic=topic, value=bytes(msg, 'utf-8'))try:# 等待消息发送完成sendResult = future.get(timeout=10)print(f"消息: {msg}\n所在的分区: {sendResult.partition}\n偏移量为: {sendResult.offset}\n")# 关闭生产producer.close()except KafkaError as e:print(f"消息: {msg} 发送失败\n失败信息为: {e}\n")

6、数据可靠性

说明:数据的可靠性保证主要是通过acks的设置来保证的,下面说明acks在不同取值下的数据可靠性情况:

  • acks=0时
    • 因为生产者发送数据后就不管了,所以当Leader或Follower发生异常时,就会发生数据丢失。
    • 实际使用很少
  • acks=1时
    • 因为生产者只需要等到Leader应答后就算完成本次发生了,但是当Leader应答完成后,还没有开始同步副本数据,Leader此时挂掉,新的Leader上线后并不会收到丢失数据,因为生产者已经认为数据发送成功了,这时就会发生数据丢失
    • 实际使用:一般用于传输普通日志
  • acks=-1时
    • 因为生产者需要等到Leader和Follower都收到数据后才算完成本次数据传输,所以可靠性高,但是当分区副本只有1个或者ISR应答的最小副本设置为1,此时和acks=1时效果一样,存在数据丢失的风险。
    • 实际使用:对可靠性要求较高的场景中,比如涉及到金钱相关的场景

综上分析:要想使得数据完全可靠条件=ACK级别设置为1 + 分区副本数大于等于2 + ISR应答最小副本数大于等于2(min.insync.replicas  参数保证)

Python代码设置acks

# acks取值:0、1、"all"
producer = KafkaProducer(bootstrap_servers=["170.22.70.174:9092", "170.22.70.178:9092", "170.22.70.179:9092"], acks=0)

7、数据去重

  • 至少一次(At Least Once)= ACK级别设置为-1 + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2;可以保证数据不丢失,但是不能保证数据不重复。
  • 最多一次(At Most Once)= ACK级别设置为0;可以保证数据不重复,但是不能保证数据不丢失。

那么如何保证数据只存储一次呢?这就需要使用幂等性。

1、幂等性

1、幂等性:

  • 1、幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证了不重复。
  • 2、精确一次(Exactly Once) = 幂等性 + 至少一次( ack=-1 + 分区副本数>=2 + ISR最小副本数量>=2) 。

2、幂等性实现原理:

  • 具有<PID, Partition, SeqNumber>相同主键的消息提交时,Broker只会持久化一条
    • 其 中PID是Kafka每次重启都会分配一个新的;
    • Partition 表示分区号;
    • Sequence Number 每次发送消息的序列号,是单调自增的。
  • 注意:幂等性只能保证的是在单分区单会话内不重复。

3、使用幂等性

  • 开启参数 enable_idempotence 默认为 true,false 关闭。
  • 目前的 kafka3 库并不支持直接设置生产者的幂等性。在 Kafka 中启用幂等性需要使用 kafka-python 或其他支持 Kafka 协议的库。
  • 以下是使用 kafka-python 库设置生产者的幂等性的示例代码:
from kafka import KafkaProducer# 创建 KafkaProducer 实例,开启幂等性
producer = KafkaProducer(bootstrap_servers="127.0.0.1:9092",acks="all",  # 设置 acks 参数为 "all",要求所有副本都确认消息enable_idempotence=True
)

8、生产者事务

说明:开启事务必须开启幂等性。

1、事务原理

存储事务信息的特殊主题:__transaction_state_分区_Leader

  • 默认有50个分区,每个分区负责一部分事务。
  • 事务划分是根据transaction.id的hash值%50,计算出该事物属于哪个分区。
  • 该分区Leader副本所在的broker节点即为这个transaction.id对应的Transaction Coordinator节点。

注意事项:生产者在使用事务功能之前,必须先自定义一个唯一的transaction.id。有了该transaction.id,即使客户端挂掉了,它重启之后也能继续处理未完成的事务。

2、使用事务

  • 目前的 kafka3 库并不支持直接创建事务。Kafka 事务的支持需要使用 kafka-python 或其他支持 Kafka 协议的库。
  • 以下是使用 kafka-python 库创建事务的示例代码:
from kafka import KafkaProducer
from kafka.errors import KafkaError# 创建 KafkaProducer 实例,开启事务
producer = KafkaProducer(bootstrap_servers="127.0.0.1:9092",enable_idempotence=True  # 开启幂等性
)# 初始化事务
producer.init_transactions()# 开始事务
producer.begin_transaction()try:# 发送事务性消息for i in range(3):key = b"my_key"value = b"my_value_%d" % iproducer.send("my_topic", key=key, value=value)# 提交事务producer.commit_transaction()except KafkaError as e:# 回滚事务producer.abort_transaction()print(f"发送消息失败: {e}")finally:# 关闭 KafkaProducer 实例producer.close()

9、数据的有序性

说明:数据的有序性只能保证单分区有序,分区与分区之间是无序的。

1、Kafka在1.x版本之前保证数据单分区有序,条件如下:

  • max.in.flight.requests.per.connection=1 (不需要开启幂等性)

2、Kafka在1.x版本之后保证数据单分区有序,条件如下:

  • 未开启幂等性
    • 设置:max.in.flight.requests.per.connection=1
  • 开启幂等性
    • 设置:max.in.flight.requests.per.connection 小于等于5
    • 原因:因为在Kafka1.x以后,启用幂等性,Kafka服务端会缓存生产者发来的最近5个request的元数据,所以至少可以保证最近5个request的数据都是有序的。

相关文章:

Kafka 生产者应用解析

目录 1、生产者消息发送流程 1.1、发送原理 2、异步发送 API 2.1、普通异步发送 2.2、带回调函数的异步发送 3、同步发送 API 4、生产者分区 4.1、分区的优势 4.2、生产者发送消息的分区策略 示例1&#xff1a;将数据发往指定 partition 示例2&#xff1a;有 key 的…...

GEE错误——image.reduceRegion is not a function

简介 image.reduceRegion is not a function 这里的主要问题是我们进行地统计分析的时候&#xff0c;我们的作用对象必须是单景影像&#xff0c;而不是影像集合 错误"image.reduceRegion is not a function" 表示你正在尝试使用reduceRegion()函数来处理图像数据&…...

rk356x 关于yocto编译linux及bitbake实用方法

Yocto 完整编译 source oe-init-build-envbitbake core-image-minimalYocto 查询包名 bitbake -s | grep XXX // 获取rockchip相关包 :~/rk3568/yocto$ bitbake -s | grep rockchip android-tools-conf-rockchip :1.0-r0 gstreamer1.0-rockchip …...

Chrome您的连接不是私密连接 |输入“thisisunsafe”命令绕过警告or添加启动参数

一、输入 thisisunsafe 在当前页面用键盘输入 thisisunsafe &#xff0c;不是在地址栏输入(切记)&#xff0c;就直接敲键盘就行了 因为Chrome不信任这些自签名ssl证书&#xff0c;为了安全起见&#xff0c;直接禁止访问了&#xff0c;thisisunsafe 这个命令&#xff0c;说明你…...

牛客面试前端1

HTML语义化 是什么 前端语义化是指在构建网页时多使用html语义化标签布局&#xff0c;多使用带有语义的标签如header&#xff0c;aside&#xff0c;footer等标签为什么 结构清晰利于开发者开发与维护 有利于seo搜索引擎优化 有利于在网络卡顿时&#xff0c;正常显示页面结构&a…...

Linux的软件包管理器-yum

文章目录 软件包的概念yum源的配置的原因yum的使用查看软件包安装软件卸载软件 软件包的概念 软件包(SoftWare Package)是指具有特定的功能&#xff0c;用来完成特定任务的一个程序或一组程序。可分为应用软件包和系统软件包两大类 在Linux系统中&#xff0c;下载安装软件的方式…...

选择排序(Selection Sort)

选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理如下: 遍历数组:从待排序的数列中,找到当前未排序部分(即整个数组或已排序部分之后的部分)中的最小(或最大,取决于排序方式)元素。 交换位置:将找到的最小元素与未排序部分的第一个元素交换位置,这…...

网络面试题目

1、BGP报文有哪些? 有5种报文,Open、 Update、 Notification、 Keepalive和 Route-refresh等5种报文类型。 2、Vxlan了解多少? VLAN作为传统的网络隔离技术,VXLAN完美地弥补了VLAN的上述不足。 VXLAN(Virtual eXtensible Local Area Network,虚拟扩展局域网),(VXL…...

Web,Sip,Rtsp,Rtmp,WebRtc,专业MCU融屏视频混流会议直播方案分析

随着万物互联&#xff0c;视频会议直播互动深入业务各方面&#xff0c;主流SFU并不适合管理&#xff0c;很多业务需要各种监控终端&#xff0c;互动SIP硬件设备&#xff0c;Web在线业务平台能相互融合&#xff0c;互联互通&#xff0c; 视频混流直播&#xff0c;录存直播推广&a…...

Unreal 编辑器工具 批量重命名资源

右键 - Editor Utilities - Editor Utility Blueprint&#xff0c;基类选择 Asset Action Utility 在类默认值内&#xff0c;可以添加筛选器&#xff0c;筛选指定的类型 然后新建一个函数&#xff0c;加上4个输入&#xff1a;ReplaceFrom&#xff0c;ReplaceTo&#xff0c;Add…...

Voice Conversion、DreamScene、X-SLAM、Panoptic-SLAM、DiffMap、TinySeg

本文首发于公众号&#xff1a;机器感知 Voice Conversion、DreamScene、X-SLAM、Panoptic-SLAM、DiffMap、TinySeg Converting Anyones Voice: End-to-End Expressive Voice Conversion with a Conditional Diffusion Model Expressive voice conversion (VC) conducts speak…...

短信群发平台分析短信群发的未来发展趋势

短信群发平台在当前的移动互联网时代已经展现出了其独特的价值和广泛的应用场景。随着技术的不断进步和市场的不断变化&#xff0c;短信群发的未来发展趋势也将呈现出一些新的特点。 首先&#xff0c;随着5G网络的推广和普及&#xff0c;短信群发的速度和稳定性将得到进一步提…...

supervisord 使用指南

supervisord 使用指南 supervisord的安装 supervisor是一系列python脚本文件&#xff0c;以python package的形式管理&#xff0c;可以用于UNIX类系统的进程管理。 安装supervisor也相当简单&#xff0c;只需要用pip安装即可。 sudo pip install supervisor但是有可能将其安…...

AngularJS 的生命周期和基础语法

AngularJS 的生命周期和基础语法 文章目录 AngularJS 的生命周期和基础语法1. 使用步骤2. 生命周期钩子函数3. 点击事件4. if 语句1. if 形式2. if else 形式 5. for 语句6. switch 语句7. 双向数据绑定 1. 使用步骤 // 1. 要使用哪个钩子函数&#xff0c;就先引入 import { O…...

docker-compose 网络

自定义网络 - HOST 与宿主机共享网络 version: "3" services:web:image: nginx:1.21.6restart: alwaysports:- 80:80network_mode: host自定义网络 - 固定ip version: "3" services:web:image: nginx:1.21.6restart: alwaysports:- 80:80networks:app&am…...

农药生产厂污废水如何处理达标

农药生产厂的污废水处理是确保该行业对环境的负面影响最小化的重要环节。下面是一些常见的处理方法和步骤&#xff0c;可以帮助农药生产厂的污废水达到排放标准&#xff1a; 预处理&#xff1a;将废水进行初步处理&#xff0c;去除大颗粒悬浮物和固体残渣。这可以通过筛网、沉淀…...

根据相同的key 取出数组中最后一个值

数组中有很多对象 , 需根据当前页面的值current 和 数组中的key对比 拿到返回值 数据结构如下 之前写法 const clickedItem routeList.find(item > item.key current) // current是当前页 用reduce遍历数组返回最后一个值 const clickedItem routeList.reduce((lastIte…...

Github Action Bot 开发教程

Github Action Bot 开发教程 在使用 Github 时&#xff0c;你可能在一些著名的开源项目&#xff0c;例如 Kubernetes&#xff0c;Istio 中看到如下的一些评论&#xff1a; /lgtm /retest /area bug /assign xxxx ...等等&#xff0c;诸如此类的一些功能性评论。在这些评论出现…...

使用docker创建rocketMQ主从结构,使用

1、 创建目录 mkdir -p /docker/rocketmq/logs/nameserver-a mkdir -p /docker/rocketmq/logs/nameserver-b mkdir -p /docker/rocketmq/logs/broker-a mkdir -p /docker/rocketmq/logs/broker-b mkdir -p /docker/rocketmq/store/broker-a mkdir -p /docker/rocketmq/store/b…...

一次完整的 http 请求是怎样的?

一次完整的 http 请求是怎样的&#xff1f; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 域名解析 --> 发起 TCP 的 3 次握手 --> 建立 TCP 连接后发起 http 请求 --> 服务器响应 http 请求&#xff0c;浏览器得到 html 代码 --…...

并行执行的概念—— 《OceanBase 并行执行》系列 一

From 产品经理&#xff1a; 这是一份姗姗来迟的关于OceanBase并行执行的系统化产品文档。 自2019年起&#xff0c;并行执行功能已被许多客户应用于多种场景之中&#xff0c;其重要性日益凸显。然而&#xff0c;遗憾的是&#xff0c;我们始终未能提供一份详尽的用户使用文档&…...

使用 ipdb 调试回调函数

一、问题概述 回调函数是指一个函数执行完后&#xff0c;调用另外一个函数的过程。 一般步骤是&#xff0c;回调函数作为参数传递给原始函数&#xff0c;原始函数执行完自己的逻辑后&#xff0c;自动调用回调函数并将自己的执行结果作为参数传递给回调函数。 根据不同的用法&a…...

介绍一下mybatis的基本配置(mybatis-config.xml)

src/main/resources/mybatis-config.xml 这句代码&#xff0c;是XML的声明&#xff0c;它指定了&#xff0c;XML的版本 和 编码方式 <?xml version"1.0" encoding"UTF-8" ?>这句代码&#xff0c;声明了XML文档类型&#xff0c;它告诉解析器&#x…...

【MySQL】第一次作业

【MySQL】第一次作业 1、在官网下载安装包2、解压安装包&#xff0c;创建一个dev_soft文件夹&#xff0c;解压到里面。3、创建一个数据库db_classes4、创建一行表db_hero5、将四大名著中的常见人物插入这个英雄表 写一篇博客&#xff0c;在window系统安装MySQL将本机的MySQL一定…...

10个免费视频素材网站,剪辑师们赶紧收藏!

剪辑师们不知道去哪里找免费视频素材&#xff0c;就上这10个网站&#xff0c;免费下载部分还可商用&#xff0c;赶紧收藏起来&#xff01; 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库虽然是个设计素材网站&#xff0c;但除了设计类素材之外还有很多…...

【毕业设计】基于SSM的运动用品商城的设计与实现

1.项目介绍 在这个日益数字化和信息化的时代&#xff0c;随着人们购物习惯的转变&#xff0c;传统的实体商店已经无法满足人们日益增长的在线购物需求。因此&#xff0c;基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的运动用品商城项目应运而生&#xff0…...

【Web】CTFSHOW 中期测评刷题记录(1)

目录 web486 web487 web488 web489 web490 web491 web492 web493 web494 web495 web496 web497 web498 web499 web500 web501 web502 web503 web505 web506 web507 web508 web509 web510 web486 扫目录 初始界面尝试文件包含index.php&am…...

vs配置cplex12.10

1.创建c空项目 2.修改运行环境 为release以及x64 3.创建cpp文件 4.鼠标右键点击项目中的属性 5.点击c/c&#xff0c;点击第一项常规&#xff0c;配置附加库目录 5.添加文件索引&#xff0c;主要用于把路径导进来 6.这一步要添加的目录与你安装的cplex的目录有关系 F:\program…...

Kubernetes 弃用Docker后 Kubelet切换到Containerd

containerd 是一个高级容器运行时&#xff0c;又名 容器管理器。简单来说&#xff0c;它是一个守护进程&#xff0c;在单个主机上管理完整的容器生命周期&#xff1a;创建、启动、停止容器、拉取和存储镜像、配置挂载、网络等。 containerd 旨在轻松嵌入到更大的系统中。Docke…...

函数模板含有多个模板参数

如果一个模板接受多个参数&#xff0c;用逗号分隔参数。 使用时必要情况下需要主动传入模板参数。 #include <iostream> #include <vector>/* Compute the greatest common divisor of two integers, using Euclids algorithm. */ template<class T, class U&g…...

网站mssql 导出数据/成都百度关键词排名

对于api 26版本及以上版本的系统&#xff0c;系统优先去读这个目录下的应用图标。 参考&#xff1a; note_35&#xff1a;Image Asset和mipmap-anydpi-v26...

怎样做网站背景/全网引流推广 价格

社会和移动零售科技商 One iota在Facebook 上发布了DealsJoy.&#xff0c;让Groupon 爱好者们又多了一个选择。 DealsJoy是一个免费的交易平台&#xff0c;遵循当下特价优惠和日常交易的潮流&#xff0c;让交易成功兑现。作为一个自助产品&#xff0c;零售商们可以把它嵌入到他…...

网站建设推广销售人员/爱站站长工具

1. 人远比技术重要 你开发软件是为了供别人使用&#xff0c;没有人使用的软件只是没有意义的数据的集合而已。许多在软件方面很有成就的行家在他们事业的初期却表现平平&#xff0c;因为他们那时侯将主要精力都集中在技术上。显然&#xff0c;构件&#xff08;components&…...

做网站一个月30ip/网站seo优化报告

上一篇文字Bootstrap研究1-精巧的网格布局系统&#xff0c;里面谈到了使用固定grid布局的原理和操作实践。关于布局部分还有一些要交代&#xff0c;权且凑为一篇。 除了固定网格布局外&#xff0c;Bootstrap还提供一种流式布局Fluid grid system&#xff0c;其就是计算当前页面…...

net和cn哪个做网站好/北京seo收费

一、io_service的作用 io_servie 实现了一个任务队列&#xff0c;这里的任务就是void(void)的函数。Io_servie最常用的两个接口是post和run&#xff0c;post向任务队列中投递任务&#xff0c;run是执行队列中的任务&#xff0c;直到全部执行完毕&#xff0c;并且run可以被N个线…...

wordpress 自动剪裁/优化网站关键词排名

之前模仿其他语言写了一个编解码类&#xff0c;运行时候发现但数据量大的时候会出问题&#xff0c;于是进行调试&#xff0c;发现如下代码 i int(byte(i)|c) 错误 后来改成如下就对了 i int(i|int(c)) 特此记录一下...