技术分享 | 为什么MGR一致性模式不推荐AFTER
- GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
1、引子
2、AFTER 的写一致性
3、AFTER 的读一致性
4、AFTER 执行流程
5、BEFORE 执行流程
6、一些思考
7、参考文档
1、引子
某次测试过程中,发现在 AFTER 级别下,节点故障会导致集群无法进行事务提交,同时,当事务进入提交阶段后,其它节点无法开启只读事务。整个集群无法正常提供服务,直到故障节点被踢出集群。
以下首先复现上述故障场景的步骤:
1、初始化一个3节点的集群。集群信息如下:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | c223cde5-0719-11ec-8295-ec5c6826bca3 | 127.0.0.1 | 13000 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | c22847e0-0719-11ec-b30b-ec5c6826bca3 | 127.0.0.1 | 13004 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | c22c3752-0719-11ec-98ef-ec5c6826bca3 | 127.0.0.1 | 13002 | ONLINE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
mysql> select @@group_replication_member_expel_timeout;
+------------------------------------------+
| @@group_replication_member_expel_timeout |
+------------------------------------------+
| 1000 |
+------------------------------------------+
1 row in set (0.00 sec)
2、在 AFTER 级别下创建表并插入一条数据
13000-conn1
mysql> set session group_replication_consistency='AFTER';
Query OK, 0 rows affected (0.00 sec)
mysql> create table t1 (c1 int primary key, c2 int);
Query OK, 0 rows affected (0.12 sec)
mysql> insert into t1 values (1,1);
Query OK, 1 row affected (0.03 sec)
3、强杀一个节点,由于设置的 expel_timeout 设置为1000秒,故障节点变成 UNREACHABLE状态
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | c223cde5-0719-11ec-8295-ec5c6826bca3 | 127.0.0.1 | 13000 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | c22847e0-0719-11ec-b30b-ec5c6826bca3 | 127.0.0.1 | 13004 | UNREACHABLE | PRIMARY | 8.0.25 |
| group_replication_applier | c22c3752-0719-11ec-98ef-ec5c6826bca3 | 127.0.0.1 | 13002 | ONLINE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
4、此时,再次插入一条数据,无法返回,语句处于等待提交阶段
13000-conn1
mysql> insert into t1 values (2,2);
13000-conn2
mysql> select time, state, info from information_schema.processlist;
+------+--------------------------------------------------------+--------------------------------------------------------------+
| time | state | info |
+------+--------------------------------------------------------+--------------------------------------------------------------+
| 0 | executing | select time, state, info from information_schema.processlist |
| 193 | waiting for handler commit | Group replication applier module |
| 228 | Waiting on empty queue | NULL |
| 193 | Slave has read all relay log; waiting for more updates | NULL |
| 50 | waiting for handler commit | insert into t1 values (2,2) |
+------+--------------------------------------------------------+--------------------------------------------------------------+
5 rows in set (0.01 sec)
5、再次登录另一个活着的节点,无法执行查询操作
13002-conn1
mysql> set @@group_replication_consistency='eventual';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
13002-conn2
mysql> select time, state, info from information_schema.processlist;
+------+--------------------------------------+--------------------------------------------------------------+
| time | state | info |
+------+--------------------------------------+--------------------------------------------------------------+
| 0 | executing | select time, state, info from information_schema.processlist |
| 354 | waiting for handler commit | Group replication applier module |
| 403 | Waiting on empty queue | NULL |
| 225 | waiting for handler commit | NULL |
| 13 | Executing hook on transaction begin. | select * from t1 |
+------+--------------------------------------+--------------------------------------------------------------+
5 rows in set (0.01 sec)
2、AFTER 的写一致性
上述故障的第一个问题是,在 MGR 集群中,当事务读写一致性级别设置为 AFTER 后,任何单点的故障都会导致集群不可用。在默认设置情况下,节点从故障到被踢出集群,一般需要5至10秒的时间,在这段时间内,整个数据库是无法进行写事务的提交的,当然,如上述测试一般,如果将expel_timeout设置的更大,则会有更长的时间无法正常工作。这对线上业务来说,将是一次灾难。
查看MGR读写一致性的原始worklog,发现上述现象是符合设计预期的,并不是一个bug。该 worklog 的以下需求即解释了上述的问题。
FR-08: When group_replication_consistency=AFTER or BEFORE_AND_AFTER,
if there are unreachable members but the group still has a
reachable majority, the transaction will wait until that
members are reachable or leave the group.
如此处理的一个好处是,可以满足部分业务对严格数据一致性的需求,但对一般的业务却是极度不友好的。因此,对于一般的业务,并不推荐使用 AFTER 机制。然而,由于非 AFTER 机制下,事务消息只是通过 paxos 协议在内存层面达成多数派,而并不要求数据落盘,因此,如果多数节点同时故障,是存在丢失数据风险的。
3、AFTER 的读一致性
上述故障的第二个问题是,当节点1 处于事务commit阶段过程中,在节点2上,甚至都无法在 eventual 级别下开启一个只读事务。此时,在故障节点被踢出集群之前,节点2无法提供任何的读写服务。
还是从 worklog 中,解释了这个问题。
FR-06: When group_replication_consistency=AFTER or BEFORE_AND_AFTER,
since the remote ONLINE members do acknowledge the
transaction on prepare, the new transactions on those members
shall be held until the preceding prepared are committed.
也就是说,如果事务在 remote 节点进入了 prepared 阶段,则必须等待该事务完成提交才能开启新的事务,不论 consistency 是何种级别。但是如此处理的一个弊端是,AFTER 级别下,不光会导致执行节点性能吞吐降低,其它节点作为只读节点性能也会降低。
在多主写部署中,性能的影响可能更大。另一个问题是,如果用户恶意开启 AFTER 级别执行一个大事务操作,会导致其它节点长时间无法开启新的事务。官方 worklog 中也提到这个问题。
SECURITY CONTEXT
================
From a point of view of malicious attack to the group, since when
group_replication_consistency=AFTER or BEFORE_AND_AFTER a
transaction will wait for a acknowledge from all ONLINE members, a
UNREACHABLE member will block a transaction execution until that
member is reachable or leaves the group.
A malicious user can set group_replication_consistency=AFTER or
BEFORE_AND_AFTER on long lived transactions, which may block new
transactions while those long lived transactions are being applied.
4、AFTER 执行流程
首先,在事务执行节点上的流程如下:
1.首先,事务进入提交阶段后,会执行一个before_commit的HOOK,在 mgr 中,对应的实现是 group_replication_trans_before_commit。AFTER 的一致性保证通过该接口实现。
2.假设事务 T1 在节点 M1 上执行,如果是 AFTER 级别,会通过 paxos 发送一个携带事务全部数据的Transaction_with_guarantee_message消息,消息类型为 CT_TRANSACTION_WITH_GUARANTEE_MESSAGE。
3.节点接收到该消息并处理时,首先会获取当前集群中的 online_members。这里需要注意的是,即使节点状态变为 UNREACHABLE,只要没有踢出集群,也会认为是 online_members。
4.节点 M1 需要等待其它节点的消息反馈
5.节点M1只有收到上述 online_members 中所有节点的 prepared 消息时,才能继续完成提交
接下来,看一下其它节点(以M2节点为例)处理 AFTER 事务的流程:
1.首先,paxos 接收到事务,并进入事务执行阶段
2.事务T1在M2进入提交阶段时,调用 before_hook进行处理,不同于 M1的用户线程,M2上的复制线程是在 GR_APPLIER_CHANNEL 上执行
3.将事务加入到 prepared 事务列表
4.发送 transaction_prepared 消息给所有的节点,并等待处理
5.接收到其它节点对 transaction_prepared 消息确认后,从 prepared 事务列表中移除该事务,并继续提交
对于 AFTER 模式,所有的节点在处理事务时,均需要发送一个 transaction_prepared 消息并等待所有节点的确认,之后,用户线程执行的事务才能成功提交。排除用户线程等待所有节点事务提交的时间开销,这些消息处理的网络开销也会对性能造成一定的影响。
另一个需要注意的是,如果在M2节点,事务T1还未进入prepared阶段,此时开启新的事务并不会阻塞。在DEBUG版本下,可以通过如下步骤进行验证。
connect 13000:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ca5023b-0a1d-11ec-82f9-c8f7507e5048 | 127.0.0.1 | 13000 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cab1e2b-0a1d-11ec-9eb9-c8f7507e5048 | 127.0.0.1 | 13004 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1caf096c-0a1d-11ec-a241-c8f7507e5048 | 127.0.0.1 | 13002 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cbc3cf7-0a1d-11ec-955d-c8f7507e5048 | 127.0.0.1 | 13006 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cc6f5eb-0a1d-11ec-8e81-c8f7507e5048 | 127.0.0.1 | 13008 | ONLINE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
5 rows in set (0.03 sec)
mysql> set session group_replication_consistency='AFTER';
Query OK, 0 rows affected (0.00 sec)
mysql> create table t1 (c1 int primary key, c2 int);
Query OK, 0 rows affected (0.17 sec)
mysql> insert into t1 values (1,1);
Query OK, 1 row affected (0.07 sec)
kill -9 13008
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ca5023b-0a1d-11ec-82f9-c8f7507e5048 | 127.0.0.1 | 13000 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cab1e2b-0a1d-11ec-9eb9-c8f7507e5048 | 127.0.0.1 | 13004 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1caf096c-0a1d-11ec-a241-c8f7507e5048 | 127.0.0.1 | 13002 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cbc3cf7-0a1d-11ec-955d-c8f7507e5048 | 127.0.0.1 | 13006 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | 1cc6f5eb-0a1d-11ec-8e81-c8f7507e5048 | 127.0.0.1 | 13008 | UNREACHABLE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
5 rows in set (0.00 sec)
connect 13002,使用DEBUG_SYNC,控制节点不进入prepared阶段:
mysql> set global debug='+d,group_replication_before_commit_hook_wait';
Query OK, 0 rows affected (0.00 sec)
connect 13000,插入新的事务,没有返回
mysql> insert into t1 values (2,2);
connect 13002,可以发现,事务被 DEBUG_SYNC 阻塞:
mysql> select command, time, state, info from information_schema.processlist;
+---------+------+----------------------------+-----------------------------------------------------------------------+
| command | time | state | info |
+---------+------+----------------------------+-----------------------------------------------------------------------+
| Connect | 189 | waiting for handler commit | Group replication applier module |
| Query | 0 | executing | select command, time, state, info from information_schema.processlist |
| Sleep | 7 | | NULL |
| Daemon | 240 | Waiting on empty queue | NULL |
| Query | 64 | debug sync point: now | NULL |
+---------+------+----------------------------+-----------------------------------------------------------------------+
5 rows in set (0.01 sec)
此时,可以查询到数据:
mysql> set session group_replication_consistency='eventual';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)
5、BEFORE 执行流程
与 AFTER 相对应的是 BEFORE,如果一个 session 开启了 BEFORE 级别,则在事务开启时,需要等待所有已经提交的事务已经在本地完成提交,这是通过 WAIT_FOR_GTID_SET 实现。在事务的开启时刻,获取到节点已经同步接收到的所有的事务 gtid 集合,并等待集合内所有的 gtid 完成提交,即可保证事务执行时,读取到最新的数据。
但是在获取 gtid 集合之前,节点需要通过 paxos 发送一个 SYNC_BEFORE_EXECUTION 类型的消息。由于 paxos 会对消息进行排队,因此,当 SYNC_BEFORE_EXECUTION 处理完成时,可以保证该消息发送之前的所有的事务消息均完成在 paxos 中的处理。由于该消息是本次事务开启时产生的,因而此时节点收到的 gtid 集合符合 BEFORE 级别。
如果节点不发送 SYNC_BEFORE_EXECUTION 消息,则 BEFORE 级别未必能够读取到最新数据。假设当前存在网络分区,总共三个节点A,B,C,网络分区后,A,B节点组成多数派,C节点为少数派,此时,A,B节点上新的写入事务将不会继续同步到C节点。在 C 节点被踢出集群之前,如果 C 开启了 BEFORE 级别,却未发送 SYNC_BEFORE_EXECUTION 消息,那么 C 中不能读取到新的数据,违背了 BEFORE 的设计宗旨。但是发送该消息后,由于无法达成消息一致性,那么新的事务将失败、或者一直等待消息返回,而不会返回用户过时的数据。
如下示例则显示了多数节点故障下,BEFORE 级别的执行行为。
开始阶段:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | dd6398ec-09fe-11ec-95de-c8f7507e5048 | 127.0.0.1 | 13002 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | dd64424b-09fe-11ec-aeeb-c8f7507e5048 | 127.0.0.1 | 13000 | ONLINE | PRIMARY | 8.0.25 |
| group_replication_applier | dd65b9de-09fe-11ec-9d06-c8f7507e5048 | 127.0.0.1 | 13004 | ONLINE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.06 sec)
mysql> select @@group_replication_member_expel_timeout;
+------------------------------------------+
| @@group_replication_member_expel_timeout |
+------------------------------------------+
| 60 |
+------------------------------------------+
1 row in set (0.00 sec)
查询数据:
mysql> set session group_replication_consistency='BEFORE';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+----+------+
| c1 | c2 |
+----+------+
| 2 | 2 |
+----+------+
1 row in set (0.01 sec)
使用kill -9模拟多数节点故障:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | dd6398ec-09fe-11ec-95de-c8f7507e5048 | 127.0.0.1 | 13002 | UNREACHABLE | PRIMARY | 8.0.25 |
| group_replication_applier | dd64424b-09fe-11ec-aeeb-c8f7507e5048 | 127.0.0.1 | 13000 | UNREACHABLE | PRIMARY | 8.0.25 |
| group_replication_applier | dd65b9de-09fe-11ec-9d06-c8f7507e5048 | 127.0.0.1 | 13004 | ONLINE | PRIMARY | 8.0.25 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
此时,再次查询数据,一直未返回
mysql> select * from t1;
使用另一个客户端查看状态,一直处于 before hook 阶段:
mysql> select command, time, state, info from information_schema.processlist;
+---------+------+--------------------------------------------------------+-----------------------------------------------------------------------+
| command | time | state | info |
+---------+------+--------------------------------------------------------+-----------------------------------------------------------------------+
| Connect | 253 | waiting for handler commit | Group replication applier module |
| Daemon | 318 | Waiting on empty queue | NULL |
| Query | 238 | Slave has read all relay log; waiting for more updates | NULL |
| Query | 170 | Executing hook on transaction begin. | select * from t1 |
| Query | 0 | executing | select command, time, state, info from information_schema.processlist |
+---------+------+--------------------------------------------------------+-----------------------------------------------------------------------+
5 rows in set (0.00 sec)
当然,由于 BEFORE 级别下,额外发送了一次 SYNC_BEFORE_EXECUTION 消息,增加了一次网络开销,对性能是有一定的影响的。
6、一些思考
AFTER 模式下,当其它节点事务进入到 prepared 阶段,但用户线程并未完成提交,此时要求新的事务开启时必须等待事务提交是否必要 ?当前设计下,这一要求会造成一定程度上的节点不可用。
AFTER 模式需要等待所有的节点提交成功,这是一个强一致的数据同步方案,但同时会导致集群不可用。同时由于参数 group_replication_consistency 是一个 session 级的控制变量,即使某一个用户连接开启 AFTER 模式,都可能导致整个集群不可用。一个备
选方案是,采用开源的GreatSQL分支的 majority-after 模式(group_replication_majority_after_mode = ON),可以规避上述问题。
7、参考文档
MySQL 设计文档(https://dev.mysql.com/worklog/task/?id=10379)
MySQL 用户文档(https://dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-consistency-guarantees.html)
Enjoy GreatSQL
文章推荐:
GreatSQL MGR FAQ
https://mp.weixin.qq.com/s/J6wkUpGXw3YkyEUJXiZ9xA
万答#12,MGR整个集群挂掉后,如何才能自动选主,不用手动干预
https://mp.weixin.qq.com/s/07o1poO44zwQIvaJNKEoPA
『2021数据技术嘉年华·ON LINE』:《MySQL高可用架构演进及实践》
https://mp.weixin.qq.com/s/u7k99y6i7riq7ScYs7ySnA
一条sql语句慢在哪之抓包分析
https://mp.weixin.qq.com/s/AYibbzl860D90rOeyjB6IQ
万答#15,都有哪些情况可能导致MGR服务无法启动
https://mp.weixin.qq.com/s/inSGpd0Q_XIl2Mb-VsvNsA
技术分享 | 为什么MGR一致性模式不推荐AFTER
https://mp.weixin.qq.com/s/rNeq479RNsklY1BlfKOsYg
关于 GreatSQL
GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
Gitee:
https://gitee.com/GreatSQL/GreatSQL
GitHub:
https://github.com/GreatSQL/GreatSQL
Bilibili:
https://space.bilibili.com/1363850082/video
微信&QQ群:
可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群
QQ群:533341697
微信小助手:wanlidbc
本文由博客一文多发平台 OpenWrite 发布!
技术分享 | 为什么MGR一致性模式不推荐AFTER的更多相关文章
- 技术分享 | 在GreatDB分布式部署模式中使用Chaos Mesh做混沌测试
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1. 需求背景与万里安全数据库软件GreatDB分布式部署模式介绍 1.1 需求背景 混沌测试是检测分布式系统不确定性.建 ...
- 技术分享 | MySQL中MGR中SECONDARY节点磁盘满,导致mysqld进程被OOM Killed
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 在MGR测试中,人为制造磁盘满问题后,节点被oom killed 问题描述 在对 ...
- 技术分享 | 简单测试MySQL 8.0.26 vs GreatSQL 8.0.25的MGR稳定性表现
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. M ...
- 技术分享|闪回在MySQL中的实现和改进
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 3306π 福州站,以下内容是由万里数据库,研发工程师唐洁分享的MySQL闪回方案完整PPT. Enjoy GreatSQ ...
- 技术分享 | Prometheus+Grafana监控MySQL浅析
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 简介 Prometheus 一套开源的监控&报警&时间序列数据库的组合,通常 Kubernetes 中都会 ...
- 技术分享 | MySQL Group Replication集群对IP地址的限制导致的一些问题与解决办法
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1. 遇到问题 测试人员小玲准备在docker环境中部署MGR集群进行一些测试,她有三个容器,容器IP分别是: 172.3 ...
- 技术分享 | MySQL数据误删除的总结
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 内容提要 用delete语句 使用drop.truncate删除表以及drop删 ...
- 技术分享 | 自制GreatSQL Docker镜像
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 近期打算制作一个GreatSQL的docker镜像,方便社区用户使用GreatSQL. 制作docker镜像的环境基于Ce ...
- 技术分享 | 测试git上2500星的闪回小工具
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1.实验环境 2.软件下载 3.开始测试 4.附参数说明 生产上发生误删数据或者误更新数据的事故时,传统恢复方法是利用备份 ...
随机推荐
- Net6 Xunit 集成测试
对于单元测试.集成测试大部分开发的朋友都懒得去写,因为这要耗费精力去设计去开发,做完项目模块直接postman 调用测试(当然这是一个选择,开发也中经常用到),但是如果测试需要多样化数据,各种场景模拟 ...
- MongoDB 分片规则
每日一句 生命本身毫无意义,只有死亡才能让你邃晓人性的真谛! 每日一句 Ideal is the beacon. Without ideal, there is no secure direction ...
- 参与 2022 第二季度 Flutter 开发者调查
2022 Google I/O 大会正式落下帷幕,Flutter 作为 14 个开发者产品和平台中的一款,吸引了来自全球的很多开发者们的关注.随着全国很多地方已经进入夏季,Flutter 今年第二季度 ...
- Druid数据库连接池使用体验
写在前面 在实际工作中我们我们使用较多的则是Spring默认的HikariDataSource数据库连接池,但是它无法提供可视化监控SQL这一能力,而这在很多场景下往往又是我们需要的功能,因此今天来学 ...
- C#语言中的类型转换方法(unfinished)
一.C#中的数据类型 1.数值类型 2.字符类型 3.字符串类型 4.布尔类型 5.枚举类型 6.Object类型 二.常见的类型转换 从转换方式的角度,类型转换分为隐式转换与显式转换两种. 其中,隐 ...
- 一文带你了解J.U.C的FutureTask、Fork/Join框架和BlockingQueue
摘要: J.U.C是Java并发编程中非常重要的工具包,今天,我们就来着重讲讲J.U.C里面的FutureTask.Fork/Join框架和BlockingQueue. 本文分享自华为云社区<[ ...
- VmWare安装Centos8注意事项
VmWare安装Centos8注意事项 1.需选择稍后安装操作系统 2.选择操作系统版本 3.修改虚拟机配置 4.配置完成点击开启虚拟机(注意要将鼠标放在屏幕中央,点击一下后才能使用上下键进行选择) ...
- 高通sensor理解
.1.高通为什么引入adsp? 2.adsp sensor 是如何工作起来的? 3.adsp 和ap 是如何通信的? 4.adsp 架构组成 解答: 1.高通在msm8960之前sensor 是挂在p ...
- 全新升级的AOP框架Dora.Interception[2]: 基于“约定”的拦截器定义方式
Dora.Interception有别于其他AOP框架的最大的一个特点就是采用针对"约定"的拦截器定义方式.如果我们为拦截器定义了一个接口或者基类,那么拦截方法将失去任意注册依赖服 ...
- SpringCloud Alibaba整合Sentinel
SpringCloud Alibaba整合Sentinel Sentinel 控制台 1. 概述 Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理.监控(单机和集群),规则 ...