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

腾讯二面:TCC分布式事务 | 图解TCC|用Go语言实现一个TCC

写在前面

前段时间,有同学反馈的一个面试问题,觉得分布式事务有点偏了,但其实也不算偏了,在java领域就有很火很成熟的seata分布式事务框架(阿里和蚂蚁的同学主导,目前在apache孵化)。
在这里插入图片描述
之前我们讲过了两阶段提交、三阶段提交(感兴趣可以翻翻历史文章),这篇文章我们就来讲讲TCC分布式事务 两提交阶段的变种,并用go语言简单实现一个TCC。详细代码在 https://github.com/CocaineCong/BiliBili-Code

原理介绍

TCC 分别代表:

  • Try:主要是对业务系统做检测及资源预留
  • Confirm:主要是对业务系统做确认提交,Try 阶段执行成功并开始执行 Confirm 阶段时,默认 Confirm 阶段是不会出错的
  • Cancel:主要是在业务执行错误,需要回滚的状态下执行的业务取消,释放预留资源

Try阶段完成业务的准备工作,Confirm阶段完成业务的提交,Cancel阶段完成事务的回滚。 基本原理如下图所示。

在这里插入图片描述

  1. 事务开始时,上层业务应用会向事务协调器注册启动事务。
  2. 业务应用会调用所有服务的Try接口,完成一阶段准备
  3. 接着业务应用调用事务协调器进行提交或者回滚事务。
  4. 事务协调器会根据Try接口返回情况,决定调用Confirm或者Cancel。如果接口调用失败,会进行重试

举个例子

我们就举一个电商平台的业务作为例子,当我们下单的时候,Try阶段需要检查以下:

  1. 检查当前账户的金额是否充足,并预留对应的金额来扣除
  2. 检查当前商品库存是否正常,并预留对应的库存
  3. 检查当前商品和当前账户的订单能否创建成功
    在这里插入图片描述

当我们Try阶段都执行成功之后,注意我们只是Try,做尝试,而不是真正的执行,就开始执行Confirm阶段:

  1. 减去对应的余额
  2. 减去库存
  3. 创建订单
    在这里插入图片描述

但如果我们Try阶段没成功,比如库存不足,或者余额不足,就开始执行Cancel阶段,因为我们Try虽然没有真正的执行,但是还是会预留预留一些资源空间出来的,我们需要将这些资源空间回滚。

  1. 回滚预留的余额
  2. 回滚库存
  3. 创建订单
    在这里插入图片描述

我们可以看到这个TCC分布式事务其实是让应用自己定义数据库操作的粒度,使得降低锁冲突和锁的粒度,提高吞吐量。

当然我们也可以看到TCC方案的不足之处:

  1. 对应用的侵入性强:业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。
  2. 实现难度较大且复杂:需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略
  3. 为了满足一致性的要求,Confirm和Cancel接口必须实现幂等

代码实现

在这里插入图片描述

我们用Go语言简单实现一下TCC吧,例子就用我们上面举的。

  • Participant:定义TCC的三个接口,Try、Confirm、Cancel
type Participant interface {Try(ctx context.Context) errorConfirm(ctx context.Context) errorCancel(ctx context.Context) error
}
  • Coordinator:定义TCC事务协调者
type Coordinator struct {participants []Participant
}
func NewCoordinator(participants ...Participant) *Coordinator {return &Coordinator{participants: participants,}
}
  • 执行TCC事务:Try阶段,全部执行,如果有错误,再全部取消(这里我实现比较暴力,感兴趣的同学可以提pr优化)
var tryErr error
for _, p := range c.participants {if err := p.Try(ctx); err != nil {// Try阶段失败,执行CanceltryErr = err}
}
if tryErr != nil {c.cancelAll(ctx)return tryErr
}
  • 如果Try阶段有error,执行CancelAll,执行所有参与者的Cancel操作
func (c *Coordinator) cancelAll(ctx context.Context) {var wg sync.WaitGrouperrChan := make(chan error, len(c.participants))for _, p := range c.participants {wg.Add(1)go func(p Participant) {defer wg.Done()if err := p.Cancel(ctx); err != nil {errChan <- fmt.Errorf("cancel failed: %w", err)}}(p)}wg.Wait() // 等待所有Cancel操作完成close(errChan)// ...
}
  • 如果Try执行正常,则进行Confirm
var confirmErr error
for _, p := range c.participants {if err := p.Confirm(ctx); err != nil {confirmErr = fmt.Errorf("confirm phase failed: %w", err)break}
}

接着我们举个account service的例子来实现TCC的Try、Confirm、Cancel接口:

在这里插入图片描述

  • account 信息服务定义:账户服务
type AccountService struct {accountID    string  // 账号amount       float64 // 总金额frozen       float64 // 预留的金额deductAmount float64 // 添加要扣减的金额字段
}
func NewAccountService(accountID string, balance float64) *AccountService {return &AccountService{accountID: accountID,amount:    balance,}
}
  • Try 函数实现 & 预留资源
func (a *AccountService) PrepareTry(amount float64) {a.deductAmount = amount // 预留出应该需要多少钱
}func (a *AccountService) Try(ctx context.Context) error {a.frozen = a.deductAmount // 冻结预留的金额a.amount -= a.deductAmount // 减去预留的金额if a.amount < 0 { // 如果小于0,也就是账号不足,返回错误return errors.New("insufficient balance")}return nil
}
  • confirm 函数实现:确认操作,实际业务中可能将冻结金额转出,扣除数据库的之类的
func (a *AccountService) Confirm(ctx context.Context) error {a.frozen = 0return nil
}
  • cancel 函数实现:取消操作,回滚预留的金额
func (a *AccountService) Cancel(ctx context.Context) error {a.amount += a.deductAmounta.frozen = 0return nil
}
  • 单测:
func TestPaymentTCCSuccess(t *testing.T) {account := NewAccountService("FanOne", 1000.0)inventory := NewInventoryService("iPhone18", 10)bizData := struct {// 准备业务数据OrderID  stringAmount   float64Quantity int}{OrderID:  "FanOne-Apple-Success",Amount:   500.0,Quantity: 2,}// 设置预留资源account.PrepareTry(bizData.Amount)inventory.PrepareTry(bizData.Quantity)coordinator := NewCoordinator(account, inventory)// 创建TCC协调者err := coordinator.Execute(context.Background())// 执行TCC事务assert.NoError(t, err)// 验证结果assert.Equal(t, 500.0, account.amount)assert.Equal(t, 0.0, account.frozen)assert.Equal(t, 8, inventory.quantity)assert.Equal(t, 0, inventory.frozen)
}

结果符合预期
在这里插入图片描述

相关文章:

腾讯二面:TCC分布式事务 | 图解TCC|用Go语言实现一个TCC

写在前面 前段时间&#xff0c;有同学反馈的一个面试问题&#xff0c;觉得分布式事务有点偏了&#xff0c;但其实也不算偏了&#xff0c;在java领域就有很火很成熟的seata分布式事务框架(阿里和蚂蚁的同学主导&#xff0c;目前在apache孵化)。 之前我们讲过了两阶段提交、三阶…...

如何在 Conda 环境中降级 Python 版本:详细指南

如何在 Conda 环境中降级 Python 版本&#xff1a;详细指南 Python 版本的管理在开发过程中至关重要&#xff0c;特别是在处理不同项目需求时。对于使用 Conda 环境的 Python 程序员来说&#xff0c;版本管理不仅仅是安装不同的 Python 版本&#xff0c;还涉及到依赖关系的兼容…...

MCP 协议解读:STDIO 高效通信与 JSON-RPC 实战

本文深度解析 MCP 协议的传输机制与消息格式&#xff0c;涵盖 stdio、SSE 及自定义传输方式&#xff0c;剖析 JSON-RPC 2.0 的请求、响应与通知设计。 结合 RooCode 开源实现与天气查询案例&#xff0c;揭秘如何通过 MCP 实现跨进程通信与高效服务集成&#xff0c;为开发者提供…...

AI心理健康服务平台项目面试实战

AI心理健康服务平台项目面试实战 第一轮提问&#xff1a; 面试官&#xff1a; 请简要介绍一下AI心理健康服务平台的核心技术架构。在AI领域&#xff0c;心理健康服务的机遇主要体现在哪些方面&#xff1f;如何利用NLP技术提升用户与AI的心理健康对话体验&#xff1f; 马架构…...

路由器重分发(OSPF+RIP),RIP充当翻译官,OSPF充当翻译官

路由器重分发&#xff08;OSPFRIP&#xff09; 版本 1 RIP充当翻译官 OSPF路由器只会OSPF语言&#xff1b;RIP路由器充当翻译官就要会OSPF语言和RIP语言&#xff1b;则在RIP中还需要将OSPF翻译成RIPOSPF 把RIP路由器当成翻译官&#xff0c;OSPF路由器就只需要宣告自己的ip&am…...

29-算法打卡-字符串-KMP算法理论2-第二十九天

1、KMP算法前缀表计算逻辑 可以查看上一章节的前缀表概念以及逻辑&#xff0c;KMP算法基础理论[基础概念、前缀、后缀、最长公共前后缀、前缀表] 2、KMP算法前缀表使用 当模式串和文本串匹配失败的时候&#xff0c;前缀表会告诉我们下一次的匹配中&#xff0c;模式串应该跳到…...

解锁生成式AI潜力的金钥匙

一、引言&#xff1a;生成式AI的浪潮与“提示词”的崛起 在短短几年内&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;以前所未有的速度席卷全球&#xff0c;从文字创作到图像生成&#xff0c;从代码辅助到科学研究&#xff0c;以ChatGPT、Midjourney、DALL…...

统计定界子数组的数组

前言&#xff1a;看到这个题目的时候&#xff0c;只想着怎么暴力枚举右端点&#xff0c;结合线段树还是会超时&#xff0c;没找到很好的处理方法 超时代码 class Tree1:def __init__(self,n):self.t [0]*(4*n)def update(self,o,l,r,index,va):if lr:self.t[o] vareturnmid …...

JAVA---字符串

ctrlN 搜索界面&#xff08;idea&#xff09; API和API帮助文档 API &#xff1a; 应用程序编程接口&#xff08;换句话说&#xff0c;就是别人已经写好了&#xff0c;我们不需要再编写&#xff0c;直接使用即可&#xff09; Java API &#xff1a;就是JDK中提供的各种功能…...

import tree # pip install dm_tree ModuleNotFoundError: No module named ‘tree‘

在导入tree包时&#xff0c;在python库里找了很久&#xff0c;一直以为是tree这个包没下载好&#xff0c;有的推荐执行 pip install dm_tree这是deepmind开发一个处理处理嵌套数据结构的库。它在某种程度上tree 概括了仅支持扁平序列的内置map函数&#xff0c;并允许将函数应用…...

Java ThreadLocal与内存泄漏

当我们利用 ThreadLocal 来管理数据时&#xff0c;我们不可避免地会面临内存泄漏的风险。 原因在于 ThreadLocal 的工作方式。当我们在当前线程的 ThreadLocalMap 中存储一个值时&#xff0c;一旦这个值不再需要&#xff0c;释放它就变得至关重要。如果不这样做&#xff0c;那么…...

Rule.resource作用说明

1. 说明 作用 Rule.resource 用于定义哪些文件需要被当前规则处理。它是对传统 test、include、exclude 的更底层封装&#xff0c;支持更灵活的匹配方式。 与 test/include/exclude 的关系 test: /.js$/ 等价于resource: { test: /.js$/ } include: path.resolve(__dirname, ‘…...

【Docker项目实战】使用Docker部署Caddy+vaultwarden密码管理工具(详细教程)

【Docker项目实战】使用Docker部署vaultwarden密码管理工具 前言一、vaultwarden介绍1.1 vaultwarden简介1.2 主要特点二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、拉取镜像五、…...

代码随想录算法训练营第五十九天 | 1.ford算法精讲 卡码网94.城市间货物运输

1.Bellman_ford 算法精讲 题目链接&#xff1a;94. 城市间货物运输 I 文章讲解&#xff1a;代码随想录 思路&#xff1a; 使用dijkstra&#xff0c;要求图中边的权值都为正数。 带负权值的单源最短路问题&#xff0c;轮到Bellman_ford 算法。Bellman_ford算法的核心思想是对…...

shell(1)

1.shell变量介绍 i.Linux Shell中的变量分为,系统变量和用户自定义变量. ii.系统变量:$HOME,$PWD, $SHELL,$USER 例echo $HOME iii.显示当前shell中的所有变量--set 2.shell变量的定义 基本语法 1.定义变量:变量名值 注意 号左右也不能有空格 2.撤销变量:unset 变量 3.声…...

KEPServerEX 6与西门子1500PLC进行OPC通讯

仿真效果与真实环境效果一至&#xff1b; 环境&#xff1a; 西门子软件&#xff1a;博图V20、S7-PLCSIM Advanced V5.0 OPC软件&#xff1a;KEPServerEX 6 创建S7-PLCSIM Advanced V5.0仿真环境 西门子1500plc组态 添加一个1500cpu&#xff0c;注意点击项目文件&#xff0…...

【概念】什么是 JWT Token?

—什么是 JWT Token&#xff1f; JWT Token&#xff08;JSON Web Token&#xff09; 就是一张后端发给前端的小票&#xff0c;里面包含用户身份信息&#xff0c;用于做无状态认证&#xff08;Stateless Authentication&#xff09;。 每次前端访问后端接口&#xff0c;都拿着…...

【Castle-X机器人】一、模块安装与调试:机器人底盘

持续更新。。。。。。。。。。。。。。。 【ROS机器人】模块安装 一、Castle-X机器人底盘1.1 结构概述1.2 驱动执行结构1.3 环境传感器1.4 电气系统1.5 Castle-x机器人底盘测试激光雷达传感器测试及数据可视化超声波传感器实时数据获取防跌落传感器测试陀螺仪测试键盘控制测试…...

NSIS打包

以下是一篇详细的 NSIS 打包 EXE 的入门教程: NSIS 打包 EXE 入门教程 NSIS(Nullsoft Scriptable Install System)是一款开源的 Windows 安装包制作工具,支持脚本化定制安装流程。本教程将带你从零开始,创建一个简单的 EXE 安装程序。 1. 环境准备 1.1 下载 NSIS 访问官…...

62.不同路径

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 示例 …...

前端开发中shell的使用场景

Shell语言基础概念 Shell是用户与操作系统内核之间的接口&#xff0c;它接收用户输入的命令并解释执行。在Linux/Unix系统中&#xff0c;Shell是最常用的命令行界面。 基本语法和常用命令 变量定义和使用 # 定义变量 name"张三" age25# 使用变量 echo $name echo…...

基于javaweb的SSM投票管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

uml类关系(实现、继承,聚合、组合,依赖、关联)

drawio和EA是架构设计时经常使用的画图工具。 drawio学习门槛低&#xff0c;使用灵活&#xff0c;但是功能仅仅限于画图。 EA学习门槛高&#xff0c;但是功能更加的丰富&#xff1a; ①在画图方面&#xff0c;EA严格满足UML标准&#xff0c;EA中的图和类是关联的&#xff0c…...

力扣热题100题解(c++)—链表

160.相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数…...

MQ消息的不可靠性发生情况与解决方案

文章目录 问题&#xff1a;可能出现的情况&#xff1a; 解决流程与兜底方案第一个方面&#xff1a;确保生产者一定把消息发送到MQ1.生产者重试机制2.生产者确认机制 第二个方面&#xff1a;确保MQ不会将消息丢失数据持久化交换机持久化2.队列持久化3.消息持久化 LazyQueue控制台…...

线程池(五):线程池使用场景问题

线程池&#xff08;五&#xff09;&#xff1a;线程池使用场景问题 线程池&#xff08;五&#xff09;&#xff1a;线程池使用场景问题1 线程池使用场景CountDownLatch、Future1.1 CountDownLatch原理示例代码 1.2 案例一&#xff08;es数据批量导入&#xff09;需求分析实现步…...

第十六届蓝桥杯网安初赛wp

解题列表 根据提示一步一步走&#xff0c;经过猜测&#xff0c;测试出app.py 经过仔细研读代码&#xff0c;找到密钥 编写python代码拿到flag key secret_key9828 flagd9d1c4d9e0d6c29e9aad71696565d99bc8d892a8979ec7a69b9a6868a095c8d89dac91d19ba9716f63b5 newbytearray(…...

8.学习笔记-Maven进阶(P82-P89)

&#xff08;一&#xff09;Maven-08-配置文件加载属性 通过maven可以做版本的集中管理&#xff0c;所以能不能通过maven进行配置文件&#xff08;jdbc.properties&#xff09;的集中管理。 &#xff08;1&#xff09;resource-》jdbc.properties 可以识别$符号 因为只能…...

基于 IPMI + Kickstart + Jenkins 的 OS 自动化安装

Author&#xff1a;Arsen Date&#xff1a;2025/04/26 目录 环境要求实现步骤自定义 ISO安装 ipmitool安装 NFS定义 ks.cfg安装 HTTP编写 Pipeline 功能验证 环境要求 目标服务器支持 IPMI / Redfish 远程管理&#xff08;如 DELL iDRAC、HPE iLO、华为 iBMC&#xff09;&…...

Ubuntu20.04部署Ragflow(Docker方式)

Ubuntu20.04部署Ragflow&#xff08;Docker方式&#xff09; Ubuntu20.04 RagflowRunning RagflowRunning Ollama 由于写这篇博客的时候电脑还没装输入法&#xff0c;所以先用半吊子英文顶着了…关于最后运行ollama的部分可以无视&#xff0c;因为我修改了端口所以才需要这么运…...

【C++语法】类和对象(2)

4.类和对象&#xff08;2&#xff09; 文章目录 4.类和对象&#xff08;2&#xff09;类的六个默认成员函数(1)构造函数&#xff1a;构造函数特点含有缺省参数的构造函数构造函数特点&#xff08;续&#xff09;注意事项构造函数补充 前面总结了有关对象概念&#xff0c;对比 C…...

JDK 17 与 Spring Cloud Gateway 新特性实践指南

一、环境要求与版本选择 1. JDK 17 的必要性 最低版本要求&#xff1a;Spring Boot 3.x 及更高版本&#xff08;如 3.4&#xff09;强制要求 JDK 17&#xff0c;以支持 Java 新特性&#xff08;如密封类、模式匹配&#xff09;和性能优化。JDK 17 核心特性&#xff1a; 密封类…...

深入了解及掌握AppScan不同测试策略的区别

引言 在当今数字化时代,应用程序安全至关重要。IBM AppScan作为一款强大的应用安全测试工具,提供了多种测试策略以适应不同的测试场景和需求。理解这些测试策略的区别,能够帮助安全测试人员更精准地开展测试工作,发现应用程序中潜藏的安全漏洞。本文将结合实际案例,深入剖…...

【Linux】web服务器的部署和优化

目录 nginx的安装与启用--/usr/share/nginx/html默认发布目录 nginx的主配置文件--/etc/nginx/nginx_conf nginx的端口 nginx默认发布文件--index.html nginx默认发布目录 nginx的访问控制 基于IP地址的访问控制 基于用户认证的访问控制 nginx的虚拟主机--/etc/nginx/…...

20250426在ubuntu20.04.2系统上解决问题mkfs.exfat command not found

20250426在ubuntu20.04.2系统上解决问题mkfs.exfat command not found 2025/4/26 21:11 缘起&#xff0c;使用NanoPi NEO开发板&#xff0c;编译FriendlyCore系统&#xff0c;打包eMMC固件的时候报错。 ./build.sh emmc-img -pack sd-card image, used to write frie…...

IDE使用技巧与插件推荐

一、高效使用技巧 1. 快捷键与操作优化 VS Code: 快速导航:Ctrl+P(Windows/Linux)或Cmd+P(macOS)打开文件搜索,输入文件名快速定位。多光标编辑:按住Alt(Windows/Linux)或Option(macOS)点击多个位置,同时编辑多处代码。Zen 模式:Ctrl+K Z(Windows/Linux)或Cmd…...

防火墙规则配置错误导致的网络问题排查

# 防火墙规则配置错误导致的网络问题排查指南 防火墙规则配置错误是网络连接问题的常见原因之一。以下是一套系统的排查步骤和方法&#xff1a; ## 1. 初步症状确认 - **常见表现**&#xff1a; - 特定服务无法访问 - 网络连接时断时续 - 部分IP地址或端口无法通信 …...

线性代数(一些别的应该关注的点)

一、矩阵 矩阵运算&#xff1a;线性变换 缩放、平移、旋转 无所不能的矩阵 - 三维图形变换_哔哩哔哩_bilibili...

思科路由器重分发(静态路由+OSPF动态路由+RIP动态路由)

路由器重分发&#xff08;静态路由OSPF动态路由RIP动态路由&#xff09; 开通端口并配置IP地址 OSPF路由 R1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shut Router(config-if)#no shutdown Router(config-if)#ip add 192.168.10.254 255.…...

2.3java运算符

运算符 1. 算术运算符 算术运算符用于执行基本的数学运算&#xff0c;像加、减、乘、除等。 运算符描述示例加法int a 5 3; // a 的值为 8-减法int b 5 - 3; // b 的值为 2*乘法int c 5 * 3; // c 的值为 15/除法int d 6 / 3; // d 的值为 2%取模&#xff08;取余&…...

元数据驱动的 AI 开发:从数据目录到模型训练自动化

元数据驱动的 AI 开发&#xff1a;从数据目录到模型训练自动化 一、引言 在人工智能技术蓬勃发展的当今时代&#xff0c;AI 开发已成为各行业实现创新的核心驱动力。然而&#xff0c;数据规模爆炸式增长、类型复杂多样、来源分散等问题&#xff0c;导致数据管理混乱、模型训练…...

从OpenAI收购实时数据引擎揭示AI数据库进化方向

第一章&#xff1a;一场技术并购背后的“数据战争” 1.1 OpenAI为何盯上Rockset&#xff1f; 当OpenAI宣布收购Rockset时&#xff0c;数据库圈层炸开了锅。这家成立于2016年的公司&#xff0c;其创始人团队堪称“数据库界梦之队”&#xff1a;CTO Dhruba Borthakur曾主导Face…...

Linux0.11内存管理:相关代码

ch13_2 源码分析 boot/head.s 页表初始化&#xff1a; 目标&#xff1a;初始化分页机制&#xff0c;将线性地址空间映射到物理内存&#xff08;前 16MB&#xff09;&#xff0c;为保护模式下的内存管理做准备。核心流程 分配页目录表和页表的物理内存空间&#xff08;通过 .…...

ShaderToy学习笔记 03.多个形状和旋转

1. 正方形和旋转 1.1. 正方形 要绘制一个正方形&#xff0c;我们需要定义一个点到正方形边界的距离函数。对于中心在原点的正方形&#xff0c;其数学表达式为&#xff1a; 对于一个点 p(x,y) 到正方形边界的距离函数可以表示为: d max(|x|, |y|) - r 其中: |x| 和 |y| 分…...

Arduino+ESP01S烧录

这种办法不使用与ThonnyMircopython 前言 这里我们使用烧录器烧录&#xff0c;淘宝十几块钱一个的东西&#xff0c;ESP01S做一个WIFI继电器还是蛮有用的&#xff0c;就是烧录起来不太方便&#xff0c;传统的办法接线麻烦&#xff0c;需多次上电&#xff0c;也可能因为电源问题…...

什么是Lua模块?你会如何使用NGINX的Lua模块来定制请求处理流程?

大家好&#xff0c;我是锋哥。今天分享关于【什么是Lua模块&#xff1f;你会如何使用NGINX的Lua模块来定制请求处理流程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是Lua模块&#xff1f;你会如何使用NGINX的Lua模块来定制请求处理流程&#xff1f; 1000道 互联…...

小白自学python第三天

学习python第三天 一、函数 1、函数介绍 函数就是组织好的&#xff0c;可重复使用的&#xff0c;用以实现特定功能的代码块。 现在我们现在需要统计多个字符串长度并且不考虑使用内置函数&#xff0c;你会怎么做&#xff1f;我们先用一种原始人办法看看吧&#xff1a; str…...

【CF】Day44——Codeforces Round 908 (Div. 2) C + Codeforces Round 1020 (Div. 3) DE

C. Anonymous Informant 题目&#xff1a; 思路&#xff1a; 比这场的D难&#xff0c;虽然也不是很难 一个很容易想到的就是由当前状态推出初始状态&#xff0c;那么怎么推呢&#xff1f; 一个性质就是如果对于某一个 x 它可以执行左移操作的话&#xff0c;那么它一定会到数组…...

深入理解HashMap:Hash冲突的解决机制

引言 HashMap 是 Java 集合框架中最常用的数据结构之一&#xff0c;它通过键值对的形式存储数据&#xff0c;并利用哈希算法实现高效的插入、删除和查询操作。然而&#xff0c;在实际使用中&#xff0c;由于哈希函数的有限性和哈希桶数量的限制&#xff0c;不可避免地会出现 哈…...

Datawhale AI春训营二期---使用AI实现老人的点餐效果(关于task2的相关思考)

文章目录 1.多次测试的结果2.分数是如何提高的3.关于上分点拨4.关于task2的收获 1.多次测试的结果 第一次和第二次的&#xff0c;都是使用的baseline: 第三次的&#xff1a; 2.分数是如何提高的 之前的几次都是通过这个baseline进行运行的&#xff0c;然后今天是了解了一下这…...