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

postgresql subtransaction以及他的效能

文章目录

  • 什么是subtransaction
  • 使用子事务
  • PL/pgSQL 中的子事务
  • 与其他数据库的兼容性
  • 运行性能测试
  • Subtransaction的实现
  • 子事务和可见性
  • 解释测试结果
  • 诊断子事务过多的问题
  • 结论

什么是subtransaction

在 PostgreSQL 中,当处于自动提交模式时,必须使用 BEGIN 或 START TRANSACTION 显式启动一个跨多个语句的事务,并用 END 或 COMMIT 结束它。如果使用 ROLLBACK 中止事务(或者在不提交的情况下结束数据库会话),事务内所做的所有工作将会被撤销。
子事务允许你撤销在事务中所做部分工作的操作。可以使用标准 SQL 语句在事务内部启动子事务:

SAVEPOINT name;

“name” 是子事务的标识符(不加单引号!)。不能在 SQL 中提交子事务(它会随包含它的事务自动提交),但可以使用以下命令回滚它:

ROLLBACK TO SAVEPOINT name;

使用子事务

子事务在较长的事务中很有用。在 PostgreSQL 中,事务内部的任何错误都将中止事务:

PgSQL
test=> BEGIN;
BEGIN
test=*> SELECT 'Some work is done';?column?      
-------------------Some work is done
(1 row)test=*> SELECT 12 / (factorial(0) - 1);
ERROR:  division by zero
test=!> SELECT 'try to do more work';
ERROR:  current transaction is aborted, commands ignored until end of transaction block
test=!> COMMIT;
ROLLBACK

如果一个事务做了很多工作,但中途失败了,这很麻烦,因为之前做的所有工作都会丢失。子事务可以帮助你从这种情况中恢复,避免重新做所有工作。

PgSQL
test=> BEGIN;
BEGIN
test=*> SELECT 'Some work is done';?column?      
-------------------Some work is done
(1 row)test=*> SAVEPOINT a;
SAVEPOINT
test=*> SELECT 12 / (factorial(0) - 1);
ERROR:  division by zero
test=!> ROLLBACK TO SAVEPOINT a;
ROLLBACK
test=*> SELECT 'try to do more work';?column?       
---------------------try to do more work
(1 row)test=*> COMMIT;
COMMIT

ROLLBACK TO SAVEPOINT 在回滚旧的子事务时,会启动另一个名为 a 的子事务。

PL/pgSQL 中的子事务

即使你从未使用过 SAVEPOINT 语句,也可能已经遇到过子事务。在 PL/pgSQL 中,上面中的代码看起来像这样:

PgSQL
BEGINPERFORM 'Some work is done';BEGIN  -- a block inside a blockPERFORM 12 / (factorial(0) - 1);EXCEPTIONWHEN division_by_zero THENNULL;  -- ignore the errorEND;PERFORM 'try to do more work';
END;

每次进入带有 EXCEPTION 子句的代码块时,都会启动一个新的子事务。离开该代码块时,子事务会被提交,而当进入异常处理器时,子事务则会被回滚。

与其他数据库的兼容性

许多其他数据库在事务内处理错误的方式不同。它们不会中止整个事务,而是仅回滚导致错误的语句,并保持事务本身处于活跃状态。
当从这样的数据库迁移或移植到 PostgreSQL 时,你可能会倾向于将每个语句都包装在一个子事务中,以模拟上述行为。
PostgreSQL 的 JDBC 驱动程序甚至有一个名为 autosave 的连接参数,你可以将其设置为 always,从而在每个语句之前自动设置一个保存点,并在出现故障时回滚。
然而,正如接下来将展示的那样,这种诱人的技巧会导致严重的性能问题。

性能测试用例
为了演示过度使用子事务所带来的问题,这里创建了一个测试表:

CREATE UNLOGGED TABLE contend (id integer PRIMARY KEY,val integer NOT NULL
)
WITH (fillfactor='50');INSERT INTO contend (id, val)
SELECT i, 0
FROM generate_series(1, 10000) AS i;VACUUM (ANALYZE) contend;

该表是一个小表,unlogged,并且设置了较低的填充因子,以尽可能减少所需的 I/O。这样,我可以更好地观察子事务的影响。
我将使用 pgbench,这是随 PostgreSQL 提供的基准测试工具,来运行以下自定义 SQL 脚本:
测试1将运行的脚本,这个脚本将产生10个savepoint(测试1中6个并行会话将产生60个子事务)

BEGIN;
PREPARE sel(integer) ASSELECT count(*)FROM contendWHERE id BETWEEN $1 AND $1 + 100;
PREPARE upd(integer) ASUPDATE contend SET val = val + 1WHERE id IN ($1, $1 + 10, $1 + 20, $1 + 30);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);DEALLOCATE ALL;
COMMIT;

测试2中的脚本,这个脚本将产生15个savepoint(测试2中6个并行会话将产生90个子事务)

BEGIN;
PREPARE sel(integer) ASSELECT count(*)FROM contendWHERE id BETWEEN $1 AND $1 + 100;
PREPARE upd(integer) ASUPDATE contend SET val = val + 1WHERE id IN ($1, $1 + 10, $1 + 20, $1 + 30);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);SAVEPOINT a;
set rnd random(1,990)
EXECUTE sel(10 * :rnd + :client_id + 1);
EXECUTE upd(10 * :rnd + :client_id);DEALLOCATE ALL;
COMMIT;

该脚本在测试1中将设置60个savepoint,在测试2中将设置90个savepoint。它使用prepare statement来最小化查询解析的开销。
pgbench 会将 :client_id 替换为每个数据库会话的唯一编号。因此,只要客户端数不超过10,每个客户端的 UPDATE 操作就不会与其他客户端发生冲突,但它们会 SELECT 彼此的行。

运行性能测试

由于我的机器有8个核心,我将使用6个并发客户端运行测试,持续十分钟。
为了在使用“perf top”时看到有意义的信息,需要安装 PostgreSQL 的debugging symbols。在生产系统上推荐使用。
Test 1 (60 subtransactions)

pgbench -f subtrans.sql -n -c 6 -T 600transaction type: subtrans.sql
scaling factor: 1
query mode: simple
number of clients: 6
number of threads: 1
duration: 600 s
number of transactions actually processed: 100434
latency average = 35.846 ms
tps = 167.382164 (including connections establishing)
tps = 167.383187 (excluding connections establishing)

这是在测试运行时,perf top --no-children --call-graph=fp --dsos=/usr/pgsql-12/bin/postgres 显示的内容:

+    1.86%  [.] tbm_iterate
+    1.77%  [.] hash_search_with_hash_value1.75%  [.] AllocSetAlloc
+    1.36%  [.] pg_qsort
+    1.12%  [.] base_yyparse
+    1.10%  [.] TransactionIdIsCurrentTransactionId
+    0.96%  [.] heap_hot_search_buffer
+    0.96%  [.] LWLockAttemptLock
+    0.85%  [.] HeapTupleSatisfiesVisibility
+    0.82%  [.] heap_page_prune
+    0.81%  [.] ExecInterpExpr
+    0.80%  [.] SearchCatCache1
+    0.79%  [.] BitmapHeapNext
+    0.64%  [.] LWLockRelease
+    0.62%  [.] MemoryContextAllocZeroAligned
+    0.55%  [.] _bt_checkkeys                                 0.54%  [.] hash_any
+    0.52%  [.] _bt_compare0.51%  [.] ExecScan

测试 2(90 个子事务)

pgbench -f subtrans.sql -n -c 6 -T 600
transaction type: subtrans.sql
scaling factor: 1
query mode: simple
number of clients: 6
number of threads: 1
duration: 600 s
number of transactions actually processed: 41400
latency average = 86.965 ms
tps = 68.993634 (including connections establishing)
tps = 68.993993 (excluding connections establishing)

“perf top --no-children --call-graph=fp --dsos=/usr/pgsql-12/bin/postgres”的内容:

+   10.59%  [.] LWLockAttemptLock
+    7.12%  [.] LWLockRelease
+    2.70%  [.] LWLockAcquire
+    2.40%  [.] SimpleLruReadPage_ReadOnly
+    1.30%  [.] TransactionIdIsCurrentTransactionId
+    1.26%  [.] tbm_iterate
+    1.22%  [.] hash_search_with_hash_value
+    1.08%  [.] AllocSetAlloc
+    0.77%  [.] heap_hot_search_buffer
+    0.72%  [.] pg_qsort
+    0.72%  [.] base_yyparse
+    0.66%  [.] SubTransGetParent
+    0.62%  [.] HeapTupleSatisfiesVisibility
+    0.54%  [.] ExecInterpExpr
+    0.51%  [.] SearchCatCache1

即使考虑到测试2中的事务比测试1多执行了一次,这仍然是一个性能下降,与测试1相比,性能回退了60%。

Subtransaction的实现

每当一个事务或子事务修改数据时,它会被分配一个事务 ID。PostgreSQL 在clog中跟踪这些事务 ID,这些日志持久保存在数据目录的 pg_xact 子目录中。
事务和子事务之间有一些区别:

  • 每个子事务都有一个包含它的事务或子事务(即“父事务”)。
  • 提交一个子事务不需要进行 WAL 刷新。
  • 每个数据库会话只能有一个事务,但可以有多个子事务。
    哪个(子)事务是给定子事务的父事务的信息保存在数据目录的 pg_subtrans 子目录中。由于这个信息在包含事务结束后就变得无效,因此不需要在关机或崩溃期间保留这些数据。

子事务和可见性

在 PostgreSQL 中,行版本(“元组”)的可见性由 xmin 和 xmax 系统列决定,这些列包含创建和销毁事务的事务 ID。如果存储的事务 ID 是一个子事务的 ID,如果存储的事务 ID 是子事务的,PostgreSQL 还需要查询包含该子事务的父事务或(父)子事务的状态,以确定该事务 ID 是否有效。。

为了确定一个语句可以看到哪些元组,PostgreSQL 在语句(或事务)开始时会对数据库进行快照。这样的快照由以下几个部分组成:

  • 最大事务 ID:在该事务之后的所有内容都是不可见的。
  • 当快照被拍摄时处于活动状态的事务和子事务列表。
  • 当前(子)事务中最早可见命令的命令号。
    快照的初始化通过查看存储在共享内存中的进程数组来完成,该数组包含有关所有当前运行的后台进程的信息。这个数组当然包含后台进程的当前事务 ID,并且每个会话最多可以容纳 64 个未中止的子事务。如果存在超过 64 个这样的子事务,快照将被标记为“suboverflowed”。

解释测试结果

一个子溢出的快照不包含确定可见性所需的所有数据,因此 PostgreSQL 有时不得不依赖 pg_subtrans。这些页面被缓存到共享缓冲区中,但可以在性能输出中看到查找它们的开销,这体现在 SimpleLruReadPage_ReadOnly 的高排名上。其他事务必须更新 pg_subtrans 以注册子事务,可以在性能输出中看到它们如何与读取者争夺轻量级锁。

诊断子事务过多的问题

除了查看“perf top”,还有其他症状可以指向这个问题的方向:
当在单线程运行时,你的工作负载表现良好,但在多个并发数据库会话中运行时表现不佳。
经常在 pg_stat_activity 中看到等待事件“SubtransSLRU”(在早期版本中称为“SubtransControlLock”)。
从 PostgreSQL v13 开始,可以查看监控视图 pg_stat_slru,检查名为 ‘Subtrans’ 的行中的 blks_read 是否持续增长。这表明 PostgreSQL 需要读取磁盘页面,因为它需要访问不再缓存的子事务。
如果使用 “pg_export_snapshot()” 函数导出快照,结果文件在数据目录的 pg_snapshots 子目录中将包含 “sof:1” 行,以指示子事务数组溢出。
从 PostgreSQL v16 开始,可以调用函数 pg_stat_get_backend_subxact(integer) 返回后端进程的子事务数量,以及子事务缓存是否溢出。

结论

子事务是一个很好的工具,但你应该明智地使用它们。如果需要并发,不要在每个事务中启动超过 64 个子事务。
找出该问题的原因可能会很棘手。例如,可能不明显的是,为 SQL 语句的每个结果行调用的包含异常处理程序的函数(可能在触发器中)会启动一个新的子事务。

相关文章:

postgresql subtransaction以及他的效能

文章目录 什么是subtransaction使用子事务PL/pgSQL 中的子事务与其他数据库的兼容性运行性能测试Subtransaction的实现子事务和可见性解释测试结果诊断子事务过多的问题结论 什么是subtransaction 在 PostgreSQL 中,当处于自动提交模式时,必须使用 BEGI…...

新手逆向实战三部曲之二——通过更改关键跳注册软件(爆破)

教程开始: 软件已无壳,具体脱壳请移步"新手逆向实战三部曲之一",这里略去查壳脱壳。 先用OD打开软件试运行了解下注册流程,以便找到突破口 经过对软件的了解,本次教程采用的是下bp MessageBoxA断点的方法找…...

高级SQL技巧:提升数据查询与分析能力的关键

高级SQL技巧:提升数据查询与分析能力的关键 在数据驱动的时代,SQL(结构化查询语言)是数据分析和数据库管理的基础工具。掌握高级SQL技巧不仅能提高查询效率,还能优化数据库结构,使数据分析和报告更加精准高…...

IntelliJ IDEA 安装 Maven 工具并更换阿里源

Maven是一个强大的项目管理工具,可以帮助Java开发者管理项目依赖、构建项目等。在IntelliJ IDEA中安装Maven工具并将其源更改为阿里源的步骤如下: 1. 安装 Maven 通过 IntelliJ IDEA 自带 Maven 打开 IntelliJ IDEA。创建或打开一个项目。点击菜单栏中…...

MIT 6.824 Lab1记录

MapReduce论文阅读 1. 编程模型 Map 函数(kv -> kv) Map 函数将输入的键值对处理为一系列中间值(键值对),并将所有的中间结果传递给 Reduce 处理。 map(String key, String value):// key: document name// val…...

C语言数据结构学习:[汇总]

介绍 这些是我在学习C语言数据结构时练习的一些题目以及个人笔记 大家也可以参考着来学习 正在更新 大家可以在我的gitee仓库 中下载笔记源文件 笔记源文件可以在Notion中导入 内容导航 C语言数据结构学习:单链表-CSDN博客...

unity游戏开发之塔防游戏

如何制作塔防游戏 让我们以迷你游戏的形式创建一个休闲塔防。 从基本处理到适用技术,应有尽有,因此您只需制作一次即可获得 Unity 中的游戏制作专业知识。 与背景素材结合使用时,您将获得以下游戏视图: 由于在创建过程中使用了 …...

前端项目接入sqlite轻量级数据库sql.js指南

前端项目接入sqlite轻量级数据库sql.js指南 引言 sql.js 是一个强大的JavaScript库,它使得SQLite数据库能够在网页浏览器中运行。这个开源项目提供了一种方式,让开发者可以在前端环境中实现轻量级的数据库操作,无需依赖服务器端数据存储&…...

模拟退火算法(Simulated Annealing)详细解读

模拟退火算法(Simulated Annealing) 是一种随机优化算法,受到物理学中金属退火过程的启发。它用于寻找全局最优解,特别适合解决组合优化问题。模拟退火算法通过模拟物质在加热和冷却过程中粒子位置的变化,逐渐寻找系统…...

(二十一)、Docker 部署 Minikube 使用可视化管理工具 Kuboard

文章目录 1、介绍docker 运行 minikube 集群节点(kube-apiserver )无法被直接访问的问题Kuboard 需要访问到 k8s 集群的kube-apiserver 2、安装 Kuboard2.1、k8s 集群节点可以被外部直接访问的情况2.1.1、下载镜像2.1.2、运行 deployment.yml2.1.3、访问…...

代码编辑组件

代码编辑组件 文章说明核心代码运行演示源码下载 文章说明 拖了很久,总算是自己写了一个简单的代码编辑组件,虽然还有不少的bug,真的很难写,在写的过程中感觉自己的前端技术根本不够用,好像总是方案不够好;…...

裴蜀定理与欧几里得算法——蓝桥杯真题中的应用

目录 裴蜀定理(Bzouts Theorem)1、定义2、推论3、欧几里得算法4、多个整数的裴蜀定理扩展 真题挑战解题思路代码实现与详细注释代码解析 裴蜀定理(Bzout’s Theorem) 1、定义 对于任意两个整数 a 和 b ,如果它们的最…...

冯诺依曼架构及CPU相关概念

一. 操作系统的概念 1. 概念 操作系统(Operating System). 首先, 所有的计算机都是由软件和硬件构成的. 而操作系统就是许许多多软件中的一种软件, 操作系统可以看作是由两部分组成: 操作系统内核系统级应用程序. 2. 作用 (1) 管理硬件设备, 调度和协调各个硬件之间的工作.…...

智能管线巡检系统:强化巡检质量,确保安全高效运维

线路巡检质量的监控是确保线路安全、稳定运行的重要环节。为了有效监控巡检质量,采用管线巡检系统是一种高效、科学的手段。以下是对如何通过管线巡检系统实现线路巡检质量监控的详细分析: 一、巡检速度监控 管线巡检系统能够实时监控巡检人员的巡检速度…...

React写关键字高亮的三个方案

1.js正则replaceAlldangerouslySetInnerHTML{{ __html: xxx }}危险属性 步骤最简单,但是是危险属性,不推荐使用,项目中实在没有头绪,可以使用它应急 通过useMemo计算得到新的状态值,赋值给dangerouslySetInnerHTML属性的__html 关键代码: const [state1, setState1] useSt…...

重塑在线软件开发新纪元:集成高效安全特性,深度解析与评估会员与促销管理系统的系统架构设计

案例 阅读以下关于软件架构设计与评估的叙述,回答问题1和问题2。 【题目】 某电子商务公司拟升级其会员与促销管理系统,向用户提供个性化服务,提高用户的粘性。在项目立项之初,公司领导层一致认为本次升级的主要目标是提升会员管…...

多层感知机的从零实现与softmax的从零实现(真·0000零基础)

今天再读zh.d2l书(4.2. 多层感知机的从零开始实现 — 动手学深度学习 2.0.0 documentation), 看了关于多层感知机的从零实现与softmax的从零实现 目录 mlp从零实现, 点击“paddle”的代码 点击“torch”的代码 训练 参数解…...

【Rust练习】18.特征 Trait

练习题来自:https://practice-zh.course.rs/generics-traits/traits.html 1 // 完成两个 impl 语句块 // 不要修改 main 中的代码 trait Hello {fn say_hi(&self) -> String {String::from("hi")}fn say_something(&self) -> String; }str…...

【自动化测试之oracle数据库】MacOs如何安装oracle- client

操作系统为Mac OS,本地在pycharm上跑自动化脚本时,因为有操作oracle数据库的部分,所以需要安装oracle数据库的客户端,并install cx_oracle,本文主要介绍如何在macOS上完成安装,并在python自动化测试代码中配置&#xf…...

Spring MVC的MultipartFile

定义 MultipartFile接口是Spring MVC中用来处理上传文件的接口,它提供了访问上传文件内容、文件名称、文件大小等信息的方法。 源码: package org.springframework.web.multipart;import java.io.File; import java.io.IOException; import java.io.I…...

vscode里如何用git

打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...