Redis与Lua原子操作深度解析及案例分析
一、Redis原子操作概述
Redis作为高性能的键值存储系统,其原子性操作是保证数据一致性的核心机制。在Redis中,原子性指的是一个操作要么完全执行,要么完全不执行,不会出现部分执行的情况。
Redis原子性的实现原理
- 单线程模型:Redis采用单线程处理命令请求,避免了多线程环境下的竞态条件
- 命令队列:所有命令按顺序执行,前一个命令执行完毕才会执行下一个
- 网络I/O多路复用:通过epoll/kqueue等机制实现高并发处理
Redis原生原子命令
Redis提供了多种原子操作命令:
• INCR/DECR
:原子增减
• SETNX
:原子设置键值(不存在时才设置)
• MSET/MGET
:批量原子操作
• HINCRBY
:哈希字段原子增减
• LPUSH/RPUSH
:列表原子操作
二、Lua脚本与原子性
当原生命令无法满足复杂业务需求时,Redis提供了Lua脚本支持来实现更复杂的原子操作。
Lua脚本的原子性保证
- 脚本整体执行:整个Lua脚本会被当作一个命令执行,在执行期间不会被其他命令打断
- 无并发干扰:脚本执行期间,Redis不会处理其他客户端请求
- 错误回滚:脚本执行出错时,已执行的操作会被回滚
Lua脚本优势
- 减少网络开销:多个操作合并为一个脚本执行
- 复杂逻辑封装:实现原生命令无法完成的复杂业务逻辑
- 性能优化:避免多次往返通信
三、Lua脚本使用详解
基本语法
-- 基本结构
local key1 = KEYS[1]
local arg1 = ARGV[1]
-- 业务逻辑
return redis.call('command', key1, arg1)
关键API
redis.call()
:执行Redis命令,出错时抛出异常并停止脚本redis.pcall()
:执行Redis命令,出错时返回错误对象而不抛出异常return
:返回脚本执行结果
脚本缓存机制
Redis会缓存SHA1摘要标识的脚本,后续可通过EVALSHA
执行缓存的脚本:
# 首次执行
SCRIPT LOAD "return redis.call('GET', KEYS[1])"
# 返回sha1摘要
EVALSHA "sha1_digest" 1 key_name
四、案例分析
案例1:分布式锁实现
-- KEYS[1]: 锁名称
-- ARGV[1]: 锁值
-- ARGV[2]: 过期时间(毫秒)
local lockKey = KEYS[1]
local lockValue = ARGV[1]
local expireTime = tonumber(ARGV[2])-- 尝试获取锁
local setResult = redis.call('SET', lockKey, lockValue, 'NX', 'PX', expireTime)if setResult thenreturn true
else-- 检查是否是当前客户端持有的锁local currentValue = redis.call('GET', lockKey)if currentValue == lockValue then-- 续期redis.call('PEXPIRE', lockKey, expireTime)return trueelsereturn falseend
end
案例2:限流器实现
-- KEYS[1]: 限流器key
-- ARGV[1]: 时间窗口(秒)
-- ARGV[2]: 最大请求数
local key = KEYS[1]
local window = tonumber(ARGV[1])
local limit = tonumber(ARGV[2])local current = redis.call('GET', key)
if current and tonumber(current) >= limit thenreturn 0
elseredis.call('INCR', key)redis.call('EXPIRE', key, window)return 1
end
案例3:库存扣减
-- KEYS[1]: 库存key
-- ARGV[1]: 扣减数量
local stockKey = KEYS[1]
local reduceAmount = tonumber(ARGV[1])-- 获取当前库存
local currentStock = tonumber(redis.call('GET', stockKey) or "0")if currentStock < reduceAmount thenreturn -1 -- 库存不足
elseredis.call('DECRBY', stockKey, reduceAmount)local remaining = redis.call('GET', stockKey)return remaining -- 返回剩余库存
end
案例4:秒杀系统实现
-- KEYS[1]: 商品库存
-- KEYS[2]: 已购用户集合
-- ARGV[1]: 用户ID
-- ARGV[2]: 商品ID
local stockKey = KEYS[1]
local boughtKey = KEYS[2]
local userId = ARGV[1]
local itemId = ARGV[2]-- 检查库存
local stock = tonumber(redis.call('GET', stockKey))
if stock <= 0 thenreturn 0 -- 库存不足
end-- 检查用户是否已购买
local isBought = redis.call('SISMEMBER', boughtKey, userId)
if isBought == 1 thenreturn 1 -- 已购买过
end-- 扣减库存并记录购买用户
redis.call('DECR', stockKey)
redis.call('SADD', boughtKey, userId)
return 2 -- 购买成功
五、性能优化与最佳实践
性能优化建议
- 保持脚本精简:避免复杂计算,将计算逻辑移到客户端
- 减少网络交互:合并多个操作为一个脚本
- 使用SCRIPT LOAD和EVALSHA:减少网络传输
- 合理设置超时:避免长时间运行的脚本阻塞Redis
最佳实践
- 参数校验:在脚本开始处验证参数有效性
- 错误处理:使用pcall捕获和处理异常
- 资源释放:确保脚本退出前释放所有资源
- 日志记录:关键操作添加日志记录
- 脚本版本管理:维护脚本版本信息
常见陷阱
- 脚本执行时间过长:可能导致Redis阻塞
- 非确定性脚本:使用随机数或时间等会导致脚本不可重复
- 过度使用脚本:简单操作应优先使用原生命令
- 内存泄漏:未清理的临时变量可能导致内存增长
六、高级应用场景
1. 分布式计数器集群
-- 跨多个节点的计数器同步
local counters = {'counter1', 'counter2', 'counter3'}
local total = 0for i, key in ipairs(counters) dototal = total + tonumber(redis.call('GET', key) or "0")
end-- 如果总数超过阈值,重置所有计数器
if total > 1000 thenfor i, key in ipairs(counters) doredis.call('SET', key, 0)end
endreturn total
2. 复杂交易处理
-- 账户A向账户B转账
local accountA = KEYS[1]
local accountB = KEYS[2]
local amount = tonumber(ARGV[1])-- 检查账户A余额
local balanceA = tonumber(redis.call('GET', accountA) or "0")
if balanceA < amount thenreturn {err = "Insufficient balance"}
end-- 执行转账
redis.call('DECRBY', accountA, amount)
redis.call('INCRBY', accountB, amount)-- 记录交易日志
local txId = redis.call('INCR', 'tx_id')
redis.call('HSET', 'tx:'..txId, 'from', accountA, 'to', accountB, 'amount', amount, 'time', redis.call('TIME')[1])return {ok = txId}
3. 排行榜维护
-- 更新用户分数并维护排行榜
local userKey = KEYS[1]
local leaderboardKey = KEYS[2]
local userId = ARGV[1]
local scoreDelta = tonumber(ARGV[2])-- 更新用户分数
local newScore = redis.call('HINCRBY', userKey, 'score', scoreDelta)-- 更新排行榜
redis.call('ZADD', leaderboardKey, newScore, userId)-- 获取用户排名
local rank = redis.call('ZREVRANK', leaderboardKey, userId)return {score = newScore, rank = rank + 1} -- Lua数组从1开始
七、监控与调试
脚本调试技巧
- 使用redis.log:在脚本中添加日志
redis.log(redis.LOG_NOTICE, "Debug info: " .. tostring(someVar))
- 分步执行:将复杂脚本拆分为多个简单脚本
- 脚本模拟器:使用redis-cli --eval测试脚本
性能监控
- SCRIPT STATS:查看脚本执行统计
- SLOWLOG:识别执行缓慢的脚本
- INFO COMMANDSTATS:查看命令执行统计
八、总结
Redis与Lua的结合为分布式系统提供了强大的原子操作能力。通过Lua脚本,开发者可以实现复杂的业务逻辑同时保证操作的原子性。在实际应用中,应根据业务场景合理选择原生命令或Lua脚本,遵循最佳实践,确保系统的高性能和数据一致性。
通过本文的深度解析和案例分析,读者应能够掌握Redis Lua脚本的核心概念、使用方法和优化技巧,并能够在实际项目中灵活应用这些知识解决复杂的分布式系统问题。
相关文章:
Redis与Lua原子操作深度解析及案例分析
一、Redis原子操作概述 Redis作为高性能的键值存储系统,其原子性操作是保证数据一致性的核心机制。在Redis中,原子性指的是一个操作要么完全执行,要么完全不执行,不会出现部分执行的情况。 Redis原子性的实现原理 单线程模型&a…...
Shell 脚本开发从入门到实战
第1章:什么是 Shell 与 Shell 脚本? 一、Shell 是什么? Shell 是一个命令解释器,是你在 Linux 里敲命令的地方。你平时用的命令如 cd、ls、echo,其实都由 Shell 来解析执行。最常见的 Shell 是 Bash,绝大…...
宇视设备视频平台EasyCVR打造智慧酒店安防体系,筑牢安全防线
一、需求背景 酒店作为人员流动频繁的场所,对安全保障与隐私保护有着极高的要求。为切实维护酒店内部公共区域的安全秩序,24小时不间断视频监控成为必要举措。通常情况下,酒店需在本地部署视频监控系统以供查看,部分连锁酒店还希…...
深度解读分销小程序商城源码系统:从搭建到运营的关键指南
在移动互联网浪潮的席卷下,电商领域持续变革与创新。分销小程序商城凭借其独特优势,如依托社交平台流量、便捷的购物体验、高效的分销推广模式等,成为众多企业和创业者开展线上业务的热门选择。深入了解分销小程序商城源码系统,从…...
BeeWorks:打造安全可控的企业内网即时通讯平台
在数字化办公时代,企业对即时通讯工具的需求日益增长,尤其是对数据安全和隐私保护有严格要求的行业,如金融、政府、医疗等。BeeWorks 作为一款专注于内网部署的即时通讯软件,凭借其卓越的安全性、稳定性、丰富的功能以及全面的信创…...
微信小程序开发:废品回收小程序-功能清单
用户端:便捷体验,触手可及 废品百科与估价指南:平台以直观的方式展示各类废品的分类标准与实时市场价格,让用户轻松掌握废品价值,决策更从容。 一键预约,轻松回收:用户只需轻触屏幕,…...
【Grok 大模型深度解析】第一期:技术溯源与核心突破
一、Grok的技术基因:从Transformer到混合架构的演进 1.1 Transformer架构的局限性 2017年Google提出的Transformer架构彻底改变了自然语言处理领域,其自注意力机制(Self-Attention)在长序列建模上表现优异。然而,随着模型规模的增大,传统Transformer暴露出以下问题: 计…...
性能比拼: Redis vs Memcached
本内容是对知名性能评测博主 Anton Putra Redis vs Memcached Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中,我们将对比 Redis 和 Memcached。我会介绍一些功能上的不同,但主要关注 性能。 首先…...
Mujoco xml actuator
actuator general(通用执行器)motor(电机执行器)position(位置伺服)velocity(速度伺服)intvelocity(积分速度伺服)damper(主动阻尼器)…...
Mybatis Plus分页查询返回total为0问题
概述 最近开发公司新项目,使用 Mybatis Plus 分页,发现总数和总页数为0,在此记录问题和解决方案。 添加 MybatisPlusConfig /*** author: lanys* version: 1.0* 创建时间:2025年4月9日 14:24:40* Description: MybatisPlus分页…...
多卡分布式训练:torchrun --nproc_per_node=5
多卡分布式训练:torchrun --nproc_per_node=5 1. torchrun 实现规则 torchrun 是 PyTorch 提供的用于启动分布式训练作业的实用工具,它基于 torch.distributed 包,核心目标是简化多进程分布式训练的启动和管理。以下是其主要实现规则: 进程启动 多进程创建:torchrun 会…...
网络层-IP地址计算
例1:IP地址二进制与十进制互转 题目: 将二进制IP 11000000.10101000.00000001.00001010 转换为点分十进制。将IP地址 172.16.254.1 转换为二进制格式。 答案与解析: 转换步骤: 每个8位二进制转为十进制: 11000000 →…...
BeagleBone Black笔记
目录 参考资料开机led控制GPIO输入输出插网线联网安装gcc编译工具镜像备份验证备份完整性将内存卡插入目标BBBboot启动开关 参考资料 链接: BeagleBone Black使用(一):狗板简介 链接: 使用Beaglebone Black的IO口 开机 直接用usb连接到电脑…...
【25软考网工笔记】第一章 计算机网络概述
目录 一、计算机网络发展与分类 1. 计算机网络形成和发展 1)ICT 2)计算机网络的发展 3)我国互联网发展 2. 计算机网络分类 1)通信子网和资源子网 2)PAN、LAN、MAN、WAN 3)其他分类方式 3. 计算机…...
Soybean Admin 配置vite兼容低版本浏览器、安卓电视浏览器(飞视浏览器)
环境 window10 pnpm 8.15.4 node 8.15.4 vite 5.1.4 soybean admin: 1.0.0 native-ui: 2.38.0 小米电视 MIUI TV版本:MiTV OS 2.7.1886(稳定版) 飞视浏览器:https://www.fenxm.com/1220.html在小米电视安装飞视浏览器可以去小红书查安装教程:…...
MicroPython 开发ESP32应用教程 之 I2S、INMP441音频录制、MAX98357A音频播放、SD卡读写
本课程我们讲解Micropython for ESP32 的i2s及其应用,比如INMP441音频录制、MAX98357A音频播放等,还有SD卡的读写。 一、硬件准备 1、支持micropython的ESP32S3开发板 2、INMP441数字全向麦克风模块 3、MAX98357A音频播放模块 4、SD卡模块 5、面包板及…...
从零到一:基于DeepSeek-R1的智能贪吃蛇开发实战
《基于DeepSeek-R1的AI驱动高性能贪吃蛇游戏开发全流程解析》 一、技术选型与环境搭建 开发工具链 • 编辑器:VSCode/Sublime(支持代码生成插件) • 运行环境:Node.js v16+(用于API调用及后端服务) • 图形库:HTML5 Canvas(网页端)或OLED驱动(单片机场景) • AI引擎…...
数据结构与算法-动态规划-区间dp,状态机dp,树形dp
3-区间 DP 介绍 通常用 (dp[i][j]) 表示区间 ([i, j]) 上的某种最优值,比如 (dp[i][j]) 可以表示从下标 (i) 到 (j) 的元素进行某种操作所得到的最大收益、最小花费等。 状态转移方程:这是区间 DP 的关键。它描述了如何从较小的区间的最优解得到较大区…...
文件内容课堂总结
Spark-Core编程 Key-Value类型: partitionBy函数根据指定Partitioner重新进行分区,默认使用HashPartitioner groupByKey函数根据key对value进行分组,有三种函数签名 reduceByKey函数将数据按相同Key对Value进行聚合,与groupByKey相…...
【树莓派Pico FreeRTOS】-任务通知
任务通知 文章目录 任务通知1、硬件准备2、软件准备3、FreeRTOS的任务通知介绍4、任务通知数据传输实例RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (…...
c++11新内容补充
1.列表初始化 1.1传统{ }初始化 c98的{ }初始化主要是用于数组,以及结构体 1.2c11{ }初始化 1.让内置类型和自定义类型都可以用{ }实现多个数据初始化,而自定义类型的实现原理是类型转换(没优化的版本是先构造临时对象,然后拷贝构…...
动态规划基础
动态规划 动态规划概论楼梯最短路最长上升子序列(LIS)最长公共子序列(LCS)最长回文子串 概率动态规划区间动态规划石子合并括号序列石子合并(环形) 树形动态规划统计人数没有上司的舞会 背包01背包完全背包多重背包分组背包 动态规…...
导入 Excel 批量替换文件名称及扩展名
重命名的需求是多种多样的,我们一个方法或一个工具很难说完全满足 100% 的文件重命名的需求。如果我们的文件重命名的需求非常的复杂的时候,我们能否有一个万全的方法来帮我们实现呢?那今天就给大家介绍一下导入 excel 的方式批量修改文件名称…...
降低AIGC检测率的AI润色提示词模板
以下是针对降低AIGC检测率的 AI润色提示词模板,涵盖语言风格优化、逻辑重构、学术规范强化等维度,结合反检测策略设计,可直接用于DeepSeek等工具: 一、标题与摘要优化 1. 标题去AI化 提示词: 请将以下标题改写成更学…...
系统思考—提升解决动态性复杂问题能力
感谢合作伙伴的信任推荐! 客户今年的人才发展重点之一,是提升管理者应对动态性、复杂性问题的能力。 在深入交流后,系统思考作为关键能力模块,最终被纳入轮训项目——这不仅是一次培训合作,更是一场共同认知的跃迁&am…...
spring--整合Mybatis详解
整合Mybatis 步骤: 1.导入相关Maven依赖 junit mybatis mysql数据库连接 spring相关的 aop织入 mybatis-spring 2.编写配置文件 3.测试 回忆mybatis 还需连接数据库 导入依赖: <dependencies><dependency><groupId>juni…...
深入理解 HTML5 Audio:网页音频播放的新时代
在网页开发领域,音频的嵌入和播放一直是一个重要且不断演进的话题。HTML5 的出现,为网页音频播放带来了标准化的解决方案,极大地改善了开发者和用户的体验。 一、HTML5 之前的音频播放状况 在 HTML5 诞生之前,互联网上缺乏统一的网页音频播放标准。当时,大多数音频播放依…...
Cloudflare 缓存工作原理
Cloudflare 缓存是 Cloudflare 内容分发网络(CDN)的一个关键组成部分,通过在靠近用户的全球网络边缘服务器上存储和交付内容,显著提升网站性能。以下是关于 Cloudflare 缓存的相关内容: 工作原理 内容请求:…...
【Unity3D中UI与物体可见性的判断方法】
系列文章目录 unity知识点 文章目录 系列文章目录👉前言👉一、判断UI的可见性1-1、第一种1-2、通过RectTransform计算可视区域1-3、滚动容器内可见性检测(Scroll View) 👉二、判断物体的可见性2-1、视锥体检测方法2-2…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(1):承上启下,继续上路
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(1):承上启下,继续上路 1、前言(1)情况说明(2)工程师的信仰2、知识点(1)普通形(ふつうけい)と思います(2)辞書形ことができます(3)Vたことがあります。(4)Vた とき & Vる とき3、单词(1)日语单词(2…...
ubuntu24.04 cmake 报错 libldap-2.5.so.0 解决办法
apt cmake有毛病 换源重新安装 wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" sudo apt update sudo apt in…...
Mac 关闭浏览器左右滑动切换页面的问题
在使用触控板,操作浏览器时,左右滑动时,浏览器容易触发前进或者后退去查看历史记录。 如何关闭呢? 打开Mac- 系统设置-触控板 -更多手势 将轻扫切换页面设置为关,就可以了...
在 openEuler 24.03 (LTS) 操作系统上添加 ollama 作为系统服务的步骤
以下是在 openEuler 操作系统上添加 ollama 作为系统服务的步骤: 创建 systemd 服务文件 sudo vi /etc/systemd/system/ollama.service将以下内容写入服务文件(按需修改参数): [Unit] DescriptionOllama Service Afternetwork.…...
华为昇腾服务器上查看固件、驱动和CANN版本的常用方法
Hey小伙伴们~👋 今天来聊聊怎么在华为昇腾服务器上查看固件、驱动和CANN版本吧!💻 这些信息对于确保你的服务器运行顺畅可是超级重要的哦!下面就来给大家介绍几种常用的查看方法!👇 🌟 1. 查…...
击球手怎么玩·棒球1号位
以棒球运动为例,在棒球运动中,击球手(Batter)是进攻方的核心角色,负责通过击球创造得分机会。以下是结合棒球运动的详细介绍和击球技巧指南: 一、棒球基础规则 比赛目标 击球手需将投手(Pitch…...
java基础多态------面试八股文
是什么是多态 类引用指向子类对象,并调用子类重写的方法,实现不同的行为 例子 class Animal {void sound() {System.out.println("动物发出声音");} }class Dog extends Animal {Overridevoid sound() {System.out.println("狗叫&…...
Python中的字典
文章目录 一、Python中的字典1. 字典的特点2. 字典的创建3. 字典的常见操作1. **访问字典中的值**2. **修改字典中的值**3. **添加键值对**4. **删除键值对**5. **检查键是否存在**6. **获取字典的长度**7. **遍历字典** 4. 字典的方法5. 嵌套字典6. 字典的优点7. 示例总结 二、…...
C++对象生命周期管理:从构造到析构的完整指南
在C开发中,准确掌握对象的生命周期管理是避免内存泄漏和资源竞争的关键。本文通过完整代码示例和内存布局分析,深入解析构造/析构顺序、继承体系、智能指针等核心机制,并分享实用调试技巧。 一、成员变量构造顺序:声明即命运 cl…...
代码随想录第14天:(二叉树)
一、找树左下角的值(Leetcode 513) 递归法: class Solution:def findBottomLeftValue(self, root: TreeNode) -> int:# 初始化最大深度为 -1,表示当前尚未遍历任何节点# 初始化 result 为 None,最终将存储最左边的…...
TCP/UDP的连接和数据发送过程详解
TCP TCP三次握手 在服务端启动好后会调用 listen() 方法,进入到 LISTEN 状态,然后静静等待客户端的连接请求到来。 而此时客户端主动调用 connect(IP地址) ,就会向某个IP地址发起第一次握手,会先建立个半连接,发送SYN…...
2. 单词个数统计
【问题描述】 编写一个程序,输入一个句子,然后统计出这个句子当中不同的单词个数。例如,对于句子“one little two little three little boys",总共有5个不同的单词,one, little, two, three, boys。 说明&…...
Js生成螺旋数组。
这段代码定义了一个名为 vetux 的函数,用于生成一个螺旋矩阵。螺旋矩阵是一种按照螺旋顺序填充数字的二维数组。以下是代码的详细解释: 函数定义 function vetux(n, m) {// 创建一个 m 行 n 列的二维数组,初始值为 0const a new Array(m).…...
《Vue.js组件化开发实战:从安全纵深到性能跃迁》
开篇:组件化开发的工业革命 当全球500强企业的核心业务系统在12.12大促中经受每秒38万次请求冲击时,我们突然意识到:现代前端组件已不再是简单的UI积木,而是承载业务逻辑、安全防护、性能优化的纳米级作战单元。本文将从军工级系统…...
【Git】--- 多人协作实战场景
Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: Git 前面我们学习了Git的所有本地仓库的相关操作:git基本操作,分支理解,版本回退,冲突解决等等。同时我们还理解了远端仓库在开发的作用以及相关操作push…...
SmolVLM2: The Smollest Video Model Ever(二)
这是对论文《SmolVLM: Redefining small and efficient multimodal models》的整理与翻译 SmolVLM:重新定义小型高效的多模态模型 拥抱脸、斯坦福大学 图1 小而强大:SmolVLM与其他最先进的小型视觉语言模型(VLM)的比较。图像结果来…...
如何通过前端表格控件实现自动化报表?1
背景 最近伙伴客户的项目经理遇见一个问题,他们在给甲方做自动化报表工具,项目已经基本做好了,但拿给最终甲方,业务人员不太买账,项目经理为此也是天天抓狂,没有想到合适的应对方案。 现阶段主要面临的问…...
数据库8(函数,变量)
1.数据类型 char(10):不足十个字符,用空格补全,数据定长;非统一字符编码,一个汉字要占两位char(2) nchar(10):不足十个字符,用空格补全,数据定长;统一字符编码,一个汉字占一位 nch…...
电阻式传感器(三)——电位器式传感器等效电路分析
(1)电位器式传感器的基本工作原理 将机械位移或其他可转换为位移变化的非电量转换为与其有一定函数关系的电阻变化,从而引起输出电压变化。 类型 基本结构 旋转型 直线型 非线性型 (2)电位器式传感器的等效电路分析 电位器式传感器的核…...
LangChain4j(1):初步认识Java 集成 LLM 的技术架构
LangChain 作为构建具备 LLM 能力应用的框架,虽在 Python 领域大放异彩,但 Java 开发者却只能望洋兴叹。LangChain4j 正是为解决这一困境而诞生,它旨在借助 LLM 的强大效能,增强 Java 应用,简化 LLM 功能在Java应用中的…...
力扣刷题——1339.分裂二叉树的最大乘积
给你一棵二叉树,它的根为 root 。请你删除 1 条边,使二叉树分裂成两棵子树,且它们子树和的乘积尽可能大。 由于答案可能会很大,请你将结果对 10^9 7 取模后再返回。 示例 1: 输入:root [1,2,3,4,5,6] 输…...