PostgreSQL 变化数据捕捉(CDC)
PostgreSQL 变化数据捕捉(CDC)
基于CDC(变更数据捕捉)的增量数据集成总体步骤:
1.捕获源数据库中的更改数据
2.将变更的数据转换为您的消费者可以接受的格式
3.将数据发布到消费者或目标数据库
PostgreSQL支持触发器(trigger)和预写日志(WAL)两种CDC机制。
如果您希望 Postgres 数据更改发生时逐行流式传输,则需要逻辑解码或 Postgres 逻辑复制功能。
使用 Postgres 逻辑解码
逻辑解码是 PostgreSQL 的基于日志的 CDC(逻辑复制)的正式名称。逻辑解码使用 PostgreSQL 预写日志的内容来存储数据库中发生的所有活动。
step1:修改PostgreSQL数据库配置postgresql.conf文件
wal_level = logical
max_replication_slots = 10
max_wal_senders = 20
wal_level :设置为 logical,允许 WAL 日志记录逻辑解码所需的信息。
max_replication_slots :确保 max_replication_slots >= 使用 WAL 的 PostgreSQL 连接器的数量加上您的数据库使用的其他复制槽的数量。
max_wal_senders :指定 WAL 的最大并发连接数的参数,确保 max_wal_senders 至少是逻辑复制槽数的两倍。例如,如果您的数据库总共使用 10 个复制槽,则该 max_wal_senders 值必须为 20 或更大。
配置修改以后,需要重复 PostgreSQL 服务生效配置。
step2:为需要同步的数据库(db)创建逻辑复制插槽(replication slot)
关于复制 SQL 函数更多详情,可以参考官方文档(9.26.系统管理函数)介绍: http://www.postgres.cn/docs/12/functions-admin.html
函数:pg_create_logical_replication_slot(slot_name name, plugin name)
返回类型:(slot_name name, lsn pg_lsn)
说明:使用输出插件plugin创建一个名为 slot_name的新逻辑(解码)复制槽。
创建时需要指定逻辑复制插槽名称和输出插件:
SELECT pg_create_logical_replication_slot('replication_slot01', 'test_decoding'); -- 使用 test_decoding 输出插件
SELECT pg_create_logical_replication_slot('replication_slot01', 'pgoutput'); -- 使用 pgoutput 输出插件
注意权限:
如果用户没有权限可能会报错:ERROR: must be superuser or replication role to use replication slots
授权:
\c - postgres
ALTER ROLE test REPLICATION; --流复制权限
\du
验证插槽是否创建成功:
SELECT * FROM pg_replication_slots;
testdb01=> SELECT * FROM pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
--------------------+---------------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------
replication_slot01 | test_decoding | logical | 16437 | testdb01 | f | f | | | 585 | 0/1807EA8 | 0/1807EE0
replication_slot02 | pgoutput | logical | 16437 | testdb01 | f | f | | | 585 | 0/1809CD8 | 0/1809D10
(2 rows)
testdb01=>
注意:
1)逻辑复制插槽名称:每个逻辑复制插槽都有一个名称,创建时需要指定名称,可以包含小写字母、数字和下划线
2)输出插件:创建逻辑复制插槽时需要指定输出插件,输出插件有:test_decoding、pgoutput、wal2json等
test_decoding 输出插件 :PostgreSQL 9.4+原生附带了 test_decoding 输出插件($PG_HOME/lib 目录下对应有 test_decoding.so),如果您的消费者支持 test_decoding ,则可以使用 test_decoding 输出插件。
pgoutput 输出插件 :PostgreSQL 10+原生附带了 pgoutput 输出插件($PG_HOME/lib 目录下对应有 pgoutput.so),如果您的消费者支持 pgoutput ,则可以使用 pgoutput 输出插件。pgoutput插件输出的是二进制的数据
wal2json 输出插件 :wal2json 是另一个流行的逻辑解码输出插件,PostgreSQL原生不携带、需要数据库服务单独安装插件才能使用。wal2json输出的是json格式的数据
step3:为数据库中的所有表或指定表创建一个发布。如果以指定表方式创建发布则后面可以在发布中管理(添加、删除)表
帮助说明:\h create publication
DROP PUBLICATION IF EXISTS pub01;
CREATE PUBLICATION pub01 FOR TABLE test01;
或者
DROP PUBLICATION IF EXISTS pub01;
CREATE PUBLICATION pub01 FOR TABLE test01, test02, test03;
或者
DROP PUBLICATION IF EXISTS pub01;
CREATE PUBLICATION pub01 FOR ALL TABLES;
查看创建发布的结果:
testdb01=> select * from pg_publication;
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate
-------+---------+----------+--------------+-----------+-----------+-----------+-------------
24629 | pub01 | 16436 | f | t | t | t | t
(1 row)
也可以执行查看:
testdb01=> \dRp
List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates
-------+-------+------------+---------+---------+---------+-----------
pub01 | test | f | t | t | t | t
(1 row)
创建发布时,还可以选择在发布中包含哪些操作。例如,下面仅创建table01表 & 仅包含INSERT和UPDATE的发布:
CREATE PUBLICATION pub01 FOR TABLE table01 WITH (publish = 'INSERT, UPDATE');
注意:
非超级用户创建发布只能指定表创建、不能 FOR ALL TABLES 创建,否则报错:ERROR: must be superuser to create FOR ALL TABLES publication
FOR ALL TABLES 只允许超级用户创建发布,或者创建后由超级用户修改已创建的发布的配置开启foralltables。
testdb01=> \c - postgres
testdb01=# update pg_publication set puballtables=true where pubname is not null; -- 设置puballtables开关
testdb01=# select * from pg_publication;
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate
-------+---------+----------+--------------+-----------+-----------+-----------+-------------
24629 | pub01 | 16436 | t | t | t | t | t
(1 row)
step4:验证指定的表是否在发布中
testdb01=> SELECT * FROM pg_publication_tables WHERE pubname='pub01';
注意:创建发布不会开始复制。它只为未来的订阅者定义一个分组和过滤逻辑。
step5:查看逻辑复制效果:
获取结果的相关命令:
pg_logical_slot_get_changes : 查询并删除数据。仅在第一次返回结果,多次调用可能会返回空结果集,这意味着当get命令执行时,结果会被提供和删除,这增强了我们编写使用这些事件创建表副本的逻辑的能力。
函数:pg_logical_slot_get_changes(slot_name name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[])
返回类型:(lsn pg_lsn, xid xid, data text)
说明:返回槽slot_name中的改变,从上一次已经被消费的点开始返回。 如果upto_lsn和upto_nchanges为 NULL,逻辑解码将一 直继续到 WAL 的末尾。如果upto_lsn为非 NULL,解码将只包括那些在指 定 LSN 之前提交的事务。如果upto_nchanges为非 NULL, 解码将在其产生的行数超过指定值后停止。不过要注意, 被返回的实际行数可能更大,因为对这个限制的检查只会在增加了解码每个新的提交事务产生 的行之后进行。
pg_logical_slot_get_binary_changes:变化数据以bytea返回。
pg_logical_slot_peek_changes : 只查询不删数据。多次调用每次都会返回相同的结果。是另一个 PostgreSQL 命令,用于在不使用 WAL 条目的情况下查看更改。
函数:pg_logical_slot_peek_changes(slot_name name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[])
返回类型:(lsn text, xid xid, data text)
说明:行为就像pg_logical_slot_get_changes()函数, 不过改变不会被消费, 即在未来的调用中还会返回这些改变。
pg_logical_slot_peek_binary_changes:变化数据以bytea返回。
关于复制 SQL 函数更多详情,可以参考官方文档(9.26.系统管理函数)介绍: http://www.postgres.cn/docs/12/functions-admin.html
测试表中I/D/U变更数据操作,然后查看逻辑复制效果:
testdb01=> SELECT * FROM pg_logical_slot_peek_changes('replication_slot01', NULL, NULL); -- 只查询不删数据
......
testdb01=> SELECT * FROM pg_logical_slot_get_changes('replication_slot01', NULL, NULL); -- 查询并删除数据
lsn | xid | data
-----------+-----+------------------------------------------------------------------------------------------
0/180A050 | 586 | BEGIN 586
0/180A050 | 586 | table public.test01: INSERT: id[bigint]:1 info[character varying]:'aa' cnt[integer]:123
0/180A160 | 586 | table public.test01: INSERT: id[bigint]:2 info[character varying]:'bb' cnt[integer]:456
0/180A1E8 | 586 | table public.test01: INSERT: id[bigint]:3 info[character varying]:'cc' cnt[integer]:55
0/180A2A0 | 586 | COMMIT 586
0/180A2A0 | 587 | BEGIN 587
0/180A2A0 | 587 | table public.test01: INSERT: id[bigint]:4 info[character varying]:'uuu' cnt[integer]:66
0/180A358 | 587 | COMMIT 587
0/180A358 | 588 | BEGIN 588
0/180A358 | 588 | table public.test01: DELETE: id[bigint]:2
0/180A3D0 | 588 | COMMIT 588
0/180A3D0 | 589 | BEGIN 589
0/180A3D0 | 589 | table public.test01: UPDATE: id[bigint]:3 info[character varying]:'xxxx' cnt[integer]:55
0/180A458 | 589 | COMMIT 589
(14 rows)
testdb01=> SELECT * FROM pg_logical_slot_get_changes('replication_slot01', NULL, NULL); -- 查询并删除数据
lsn | xid | data
-----+-----+------
(0 rows)
testdb01=>
pgoutput输出插件的结果查看,则执行:
testdb01=> SELECT * FROM pg_logical_slot_peek_binary_changes('replication_slot02', null, null, 'proto_version', '1', 'publication_names', 'pub01'); -- 查询但不删除数据
......
testdb01=> SELECT * FROM pg_logical_slot_get_binary_changes('replication_slot02', null, null, 'proto_version', '1', 'publication_names', 'pub01'); -- 查询并删除数据
lsn | xid | data
-----------+-----+------------------------------------------------------------------------------------------------------------------------------
0/1809DF8 | 585 | \x420000000001809fd0000296c5f556e57d00000249
0/1809DF8 | 585 | \x52000060417075626c696300746573743031006400030169640000000014ffffffff00696e666f00000004130000006800636e740000000017ffffffff
0/1809DF8 | 585 | \x44000060414b00037400000001316e6e
0/1809F40 | 585 | \x44000060414b00037400000001346e6e
0/1809F88 | 585 | \x44000060414b00037400000001336e6e
0/180A000 | 585 | \x43000000000001809fd0000000000180a000000296c5f556e57d
0/180A050 | 586 | \x42000000000180a270000296c5f7bb75300000024a
0/180A050 | 586 | \x49000060414e0003740000000131740000000261617400000003313233
0/180A160 | 586 | \x49000060414e0003740000000132740000000262627400000003343536
0/180A1E8 | 586 | \x49000060414e00037400000001337400000002636374000000023535
0/180A2A0 | 586 | \x4300000000000180a270000000000180a2a0000296c5f7bb7530
0/180A2A0 | 587 | \x42000000000180a328000296c5f7d8abe90000024b
0/180A2A0 | 587 | \x49000060414e0003740000000134740000000375757574000000023636
0/180A358 | 587 | \x4300000000000180a328000000000180a358000296c5f7d8abe9
0/180A358 | 588 | \x42000000000180a3a0000296c5f80ae6ca0000024c
0/180A358 | 588 | \x44000060414b00037400000001326e6e
0/180A3D0 | 588 | \x4300000000000180a3a0000000000180a3d0000296c5f80ae6ca
0/180A3D0 | 589 | \x42000000000180a428000296c5f826073e0000024d
0/180A3D0 | 589 | \x55000060414e000374000000013374000000047878787874000000023535
0/180A458 | 589 | \x4300000000000180a428000000000180a458000296c5f826073e
(20 rows)
testdb01=> SELECT * FROM pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
--------------------+---------------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------
replication_slot01 | test_decoding | logical | 16437 | testdb01 | f | f | | | 590 | 0/180A540 | 0/180A578
replication_slot02 | pgoutput | logical | 16437 | testdb01 | f | f | | | 590 | 0/180A540 | 0/180A578
(2 rows)
PG logical replication plug-in ("pgoutput") 输出的消息格式详情可以参考PG官方说明:https://www.postgresql.org/docs/10/protocol-logicalrep-message-formats.html
step6:销毁逻辑复制插槽
SELECT pg_drop_replication_slot('replication_slot01');
使用复制插槽的注意事项:
1)每个插槽只有一个输出插件(创建插槽时由您来选择使用哪个)。
2)每个插槽仅提供来自一个数据库的更改。
3)一个数据库可以有多个插槽。
4)每个数据更改通常在每个插槽中发出一次。
5)但是当 Postgres 实例重新启动时,插槽可能会重新发出更改。消费者必须处理这种情况。
6)未使用的插槽对 Postgres 实例的可用性构成威胁。Postgres 将为这些未使用的更改保存所有 WAL 文件。这可能导致存储溢出。
关于 PostgreSQL WAL 消费者:
可以获取 Postgres 逻辑解码流的任何应用程序都是 PostgreSQL WAL 消费者。
pg_recvlogical:
pg_recvlogical 是一个 PostgreSQL 应用程序,他是 PostgreSQL 原生的逻辑解码工具,它可以管理槽并使用槽中的流。它包含在 Postgres 发行版中,因此它可能已经随 PostgreSQL 一起安装,在 $PG_HOME/bin 目录下。
pg_recvlogical 使用默认的 test_decoding 逻辑解码插件,pg安装完后会在pg安装目录的lib目录下创建test_decoding链接库文件。
pg_recvlogical 使用介绍:
创建逻辑复制插槽:
$ pg_recvlogical --create-slot -S replication_slot01 -d testdb01
启动复制槽解码(启动后会实时的将日志解码到制定的文件中,也可以不启动、等需要解码时再启动解码)
$ pg_recvlogical --start -S replication_slot01 -d testdb01 -f replication_slot01_decoding.log &
查看解码结果:
$ cat replication_slot01_decoding.log
查看数据库lsn:
postgres=# select pg_current_wal_lsn();
使用pg_recvlogical进行日志区间解码:
$ pg_recvlogical --start -S replication_slot01 -d testdb01 -I 4C/180B020 -E 4C/180B1EE -f ret.log
相关文章:
PostgreSQL 变化数据捕捉(CDC)
PostgreSQL 变化数据捕捉(CDC)基于CDC(变更数据捕捉)的增量数据集成总体步骤:1.捕获源数据库中的更改数据2.将变更的数据转换为您的消费者可以接受的格式3.将数据发布到消费者或目标数据库PostgreSQL支持触发器&#x…...
Spring 事务【隔离级别与传播机制】
Spring 事务【隔离级别与传播机制】🍎一.事务隔离级别🍒1.1 事务特性回顾🍒1.2 事务的隔离级别(5种)🍒1.3 事务隔离级别的设置🍎二.Spring 事务传播机制🍒2.1 Spring 事务传播机制的作用🍒2.2 事…...
HTTP和HTTPS协议
HTTP协议 HTTP协议是一种应用层的协议,全称为超文本传输协议。 URL URL值统一资源定位标志,也就是俗称的网址。 协议方案名 http://表示的就是协议方案名,常用的协议有HTTP协议、HTTPS协议、FTP协议等。HTTPS协议是以HTTP协议为基础&#…...
day3——有关java运算符的笔记
今天主要学习的内容有java的运算符 赋值运算符算数运算符关系运算符逻辑运算符位运算符(专门写一篇笔记)条件运算符运算符的优先级流程控制 赋值运算符 赋值运算符()主要用于给变量赋值,可以跟算数运算符相结合&…...
Git多人协同远程开发
1. 李四(项目负责人)操作步骤 在github中创建远程版本库testgit将基础代码上传⾄testgit远程库远程库中基于main分⽀创建dev分⽀将 githubleaflife/testgit 共享给组员李四继续在基础代码上添加⾃⼰负责的模块内容 2. 张三、王五(组员&…...
Chapter4:机器人仿真
ROS1{\rm ROS1}ROS1的基础及应用,基于古月的课,各位可以去看,基于hawkbot{\rm hawkbot}hawkbot机器人进行实际操作。 ROS{\rm ROS}ROS版本:ROS1{\rm ROS1}ROS1的Melodic{\rm Melodic}Melodic;实际机器人:Ha…...
python(14)--集合
前言 本篇文章学习的是 python 中集合的基础知识。 集合元素的内容是不可变的,常见的元素有整数、浮点数、字符串、元组等。至于可变内容列表、字典、集合等不可以是集合元素。虽然集合不可以是集合的元素,但是集合本身是可变的,可以去增加或…...
【Spark分布式内存计算框架——Spark Core】4. RDD函数(中)Transformation函数、Action函数
3.2 Transformation函数 在Spark中Transformation操作表示将一个RDD通过一系列操作变为另一个RDD的过程,这个操作可能是简单的加减操作,也可能是某个函数或某一系列函数。值得注意的是Transformation操作并不会触发真正的计算,只会建立RDD间…...
Mysql 数据类型
1、数值数据类型 1.1 整数类型(精确值) INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT MySQL支持SQL标准的整数类型INTEGER (或INT)和SMALLINT。作为标准的扩展,MySQL还支持整数类型TINYINT、MEDIUMINT和BIGINT。下表显示了每种整数类型所需的存储和范围。…...
运行Whisper笔记(1)
最近chatGPT很火,就去逛了一下openai的github项目。发现了这个项目。 这个项目可以识别视频中的音频,转换出字幕。 带着一颗好奇的心就尝试自己去部署玩一玩 跟着这篇文章一步步来进行安装,并且跟着这篇文章解决途中遇到的问题。 途中还会遇…...
2023年最强大的12款数据可视化工具,值得收藏
做数据分析也有年头了,好的坏的工具都用过,推荐几个觉得很好用的,避坑必看! PS:一般比较成熟的公司里,数据分析工具不只是满足业务分析和报表制作,像我现在给我们公司选型BI工具,是做…...
LeetCode刷题系列 -- 523. 连续的子数组和
给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:子数组大小 至少为 2 ,且子数组元素总和为 k 的倍数。如果存在,返回 true ;否则,返回 false 。如果存…...
LeetCode刷题系列 -- 525. 连续数组
给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。示例 1:输入: nums [0,1]输出: 2说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。示例 2:输入: nums [0,1,0]输出: 2说明: [0, 1] (或 [1, 0]) 是具有相同数…...
JavaEE15-Spring Boot统一功能处理
目录 1.统一用户登录权限效验 1.1.最初用户登录验证 1.2.Spring AOP用户统一登录验证的问题 1.3.Spring拦截器 1.3.1.创建自定义拦截器,实现 HandlerInterceptor 接口并重写 preHandle(执行具体方法之前的预处理)方法 1.3.2.将自定义拦…...
centos7.6 设置防火墙
1、查看系统版本 cat /etc/redhat-release2、查看防火墙运行状态 systemctl status firewalld这里可以看到当前是未运行状态(inactive)。 3、关闭开机自启动防火墙 systemctl disable firewalld.service4、启动防火墙并查看状态,系统默认 22 端口是开启的。 sy…...
在线支付系列【22】微信支付实战篇之集成服务商API
有道无术,术尚可求,有术无道,止于术。 文章目录前言1. 环境搭建2. 特约商户进件3. 统一下单总结前言 在上篇文档中,我们做好了接入前准备工作,接下来使用开源框架集成服务商相关API。 一个简单的支付系统完成支付流程…...
3.2 埃尔米特转置
定义 对于复矩阵,转置又不一样,常见的操作是共轭转置,也叫埃尔米特转置Hermitian transpose。埃尔米特转置就是对矩阵先共轭,再转置,一般来说用三种符号表示埃尔米特转置: 第一种符号是AHA^HAH,…...
Python爬虫之Scrapy框架系列(13)——实战ZH小说爬取数据入MySql数据库
目录:1 数据持久化存储,写入Mysql数据库①定义结构化字段:②重新编写爬虫文件:③编写管道文件:④辅助配置(修改settings.py文件):⑤navicat创库建表:⑥ 效果如下…...
MySQL篇02-三大范式,多表查询
数据入库时,由于数据设计不合理,会存在数据重复、更新插入异常等情况, 故数据库中表的设计遵循的设计规范:三大范式1.第一范式(1NF)要求数据库的每一列都是不可分割的原子数据项,即原子性。强调的是列的原子性,即数据库中每一列的…...
vue-cli3创建Vue项目
文章目录前言一、使用vue-cli3创建项目1.检查当前vue的版本2.下载并安装Vue-cli33.使用命令行创建项目二、关于配置前言 本文讲解了如何使用vue-cli3创建属于自己的Vue项目,如果本文对你有所帮助请三连支持博主,你的支持是我更新的动力。 下面案例可供…...
Linux perf probe 的使用(三)
文章目录前言一、Dynamic Tracing二、kprobes2.1 perf kprobe 的使用2.2 kprobe Arguments3.3 tcp_sendmsg()3.3.1 Kernel: tcp_sendmsg()3.3.2 Kernel: tcp_sendmsg() with size3.3.2 Kernel: tcp_sendmsg() line number and local variable三、uprobes的使用3.1 perf uprobe …...
python GUI编程 多窗口跳转
# 多窗口跳转例子from tkinter import *def main(): # 主窗体def goto(num):root.destroy() # 关闭主窗体if num 1:one() # 进入第1个窗体elif num 2:two() # 进入第2个窗体root Tk()root.geometry(300x150600200)root.title(登录窗口)but1 Button(root, text"进入…...
nuxt 学习笔记
这里写目录标题路由跳转NuxtLinkquery参数params参数嵌套路由tab切换效果layouts 文件夹强制约定放置所有布局文件,并以插槽的形式作用在页面中1.在app.vue里面2.component 组件使用Vue < component :is"">Vuex生命周期数据请求useFetchuseAsyncDat…...
Python编程自动化办公案例(1)
作者简介:一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页 目录 前言 一.使用库讲解 1.xlrd 2.xlwt 二.主要案例 1.批量合并 模板如下…...
一站式 Elasticsearch 集群指标监控与运维管控平台
上篇文章写了一下消息运维管理平台,今天带来的是ES的监控和运维平台。目前初创企业,不像大型互联网公司,可以重复的造轮子。前期还是快速迭代试错阶段,方便拿到市场反馈,及时调整自己的战略和产品方向。让自己活下去&a…...
C# 调用Python
一、简介 IronPython 是一种在 NET 和 Mono 上实现的 Python 语言,由 Jim Hugunin(同时也是 Jython 创造者)所创造。 Python是一种跨平台的计算机程序设计语言。 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python是…...
51单片机最强模块化封装(3)
文章目录 前言一、创建smg文件,添加smg文件路径二、smg文件编写三、模块化测试总结前言 本篇文章将带大家继续封装我们的代码。 这里我们会封装数码管的操作函数。 一、创建smg文件,添加smg文件路径 这里的操作就不过多解释了,大家自行看前面的文章即可。 51单片机模块化…...
【CSS 布局】水平垂直居中
CSS 布局-水平垂直居中 一、水平居中 创建一个父盒子,和子盒子 <div class"parent"><div class"child"></div> </div>基本样式如下 .parent {background-color: #fff; }.child {background-color: #999;width: 100p…...
【C++】类和对象--类的6个默认成员函数
目录1.类的6个默认成员函数2.构造函数2.1概念2.2特性3.析构函数3.1概念3.2特性4.拷贝构造函数4.1概念4.2特征5.赋值运算符重载5.1运算符重载5.2赋值运算符重载5.3前置和后置重载5.4流插入和流提取运算符重载6.const成员7.取地址重载和const取地址操作符重载1.类的6个默认成员函…...
常见面试题---------如何处理MQ消息丢失的问题?
如何处理MQ消息丢失的问题? RabbitMQ丢失消息分为如下几种情况: 生产者丢消息: 生产者将数据发送到RabbitMQ的时候,可能在传输过程中因为网络等问题而将数据弄丢了。 RabbitMQ自己丢消息: 如果没有开启RabbitMQ的持久化&#x…...
如何自己做网站手机软件/福州seo博客
通过最近对 Flutter 开发的大致了解,感受最深的简单概括就是:Widget 就是一切外加组合和响应式,我们开发的界面,通过组合其他的 Widget 来实现,当界面发生变化时,不会像我们原来 iOS 或者 Andriod 开发一样…...
北京天通苑 做网站/百度排行
error C2664: CreateThread2010-06-24 17:21用VC创建新线程易出的问题error C2664: CreateThread : cannot convert parameter 3 from unsigned long (void *) to unsigned long (__stdcall *)(void *) 收藏 今天使用 CreateThread 方法创建线程遇到问题,后解决&…...
医院门户网站设计/深圳推广公司
一、环境搭建 1、创建父工程 新建父工程项目springcloud,切记Packaging是pom模式 主要是定义POM文件,将后续各个子模块公用的jar包等统一提取出来,类似一个抽象父类 pom.xml <?xml version"1.0" encoding"UTF-8"?…...
wordpress增加购物车/世界杯积分榜排名
匿名函数和闭包 学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。 一.匿名函数 //普通函数 function box() { //函数名是box return Lee; } //匿名函数 function () { //匿名函数ÿ…...
推广网站链接怎么做/百度口碑网
KEIL uVision,KEIL MDK,KEIL For ARM,RealView MDK,KEIL C51,KEIL C166,KEIL C251 从接触MCS-51单片机开始,我们就知道有一个叫KEIL的软件。在开发单片机时,使用的是C语言或者汇编语…...
现在建网站还能赚钱吗/万能导航网
2019独角兽企业重金招聘Python工程师标准>>> 高性价比深度学习神器!阿里云GPU实例V100 最深度评测 在 GTC 2017 大会上,NVIDIA 的 CEO 黄仁勋正式发布了其新一代旗舰计算卡 Tesla V100,但是一项技术从发布到真正使用到生产环境中&…...