学废SpringBoot+Redis+Lua=王炸(值得珍藏)

1. Lua语言

1.1 Lua简介

Lua是一种轻量级、可嵌入的脚本语言,广泛应用于游戏开发、Web开发和其他领域。其简洁的语法和强大的功能使其成为一种高效、易用的编程语言。Lua语言的设计原则是提供一种易于学习、易于使用且具有强大功能的语言,让程序员能够更加高效地编写代码。

1.2 Lua语言特性

  1. 语法简洁明了

Lua语言的语法非常简洁明了,易于学习。它采用了一种类似C语言的语法风格,但更加简单。通过使用关键字、变量和函数,可以轻松地编写出高效的代码。

  1. 数据类型丰富

Lua语言拥有丰富的数据类型,包括数字、字符串、布尔值、表(数组和字典的集合)等。这些数据类型使得Lua语言能够处理各种复杂的数据结构和算法。

  1. 函数作为第一类公民

在Lua语言中,函数被视为第一类公民,这意味着函数可以作为变量传递、作为返回值以及创建新的函数。这种设计使得函数成为代码重用和抽象的重要工具。

  1. 闭包和匿名函数

Lua语言支持闭包和匿名函数,这使得代码更加简洁且易于维护。闭包允许函数在定义时捕获并使用外部变量,而匿名函数则可以在没有名称的情况下定义函数。

1.3 Lua语法介绍

Lua语言的语法非常简洁,设计原则是易于学习、使用和阅读。以下是对Lua语法的详细介绍:

  1. 变量赋值:在Lua中,变量赋值非常简单。只需使用变量名,后接等号,然后是值即可。例如,全局变量在默认情况下是可用的,可以通过简单的赋值来定义它们:

    a = 1
    

    如果想要声明一个局部变量,需要使用local关键字:

    local b = 2
    
  2. 数据类型:Lua是一种动态类型语言,这意味着你不需要预先声明变量的类型。Lua有8种基本类型:nilbooleannumberstringuserdatafunctionthreadtable

    Lua中的nil是一种特殊类型的值,它的含义是“无”或者“空”。它是Lua中唯一的类型,表示一个变量没有值。

    当一个变量被声明了,但没有被赋值时,它的值就是nil(nil在Lua中并不表示“假”或者“空字符串”)。

    例如:

    -- 声明不同类型的变量  
    local num = 42  -- 整数  
    local num2 = 3.14  -- 浮点数
    local bool1 = true  -- true  
    local bool2 = false  -- false
    local str1 = "Hello, World!"  -- 双引号字符串  
    local str2 = 'Lua is great!'  -- 单引号字符串-- 创建协程
    local cdata = coroutine.create(function () print("Hello from coroutine!") end)  -- 定义函数  
    local function say_hello(name) print("Hello, " .. name) end  
    -- 调用函数,输出 "Hello, Alice"
    say_hello("Alice")  -- 创建线程  
    local thread = coroutine.create(function () print("Hello from thread!") end)  
    -- 恢复线程,输出 "Hello from thread!"
    coroutine.resume(thread) local x  -- x没有被赋值,所以它的值是nil  
    print(x)  -- 输出nil
    
  3. 流程控制:Lua提供了常用的流程控制结构,如if-elsewhilefor。例如:

    if age < 18 thenprint("未成年")
    elseif age >= 18 and age < 65 thenprint("成年")
    elseprint("老年")
    end-- 循环结构
    for i = 1, 5 doprint(i)
    endlocal count = 0
    while count < 3 doprint("循环次数: " .. count)count = count + 1
    endrepeatprint("至少执行一次")
    until count > 5
    
  4. 函数:在Lua中,函数是一等公民。这意味着函数可以作为参数传递,也可以作为返回值。定义一个函数的基本语法如下:

    function add(a, b)return a + b
    endlocal result = add(5, 3)
    print("5 + 3 = " .. result)
    

    或者使用简洁声明方式:

    functionName = function(parameters)  -- 函数体  
    end
    
  5. 闭包和匿名函数:闭包允许一个函数记住并访问其词法环境,即使该函数是在其他地方调用的。匿名函数是没有名称的函数,可以作为参数传递或赋值给变量。例如:

    local function createCounter()   local count = 0   return function()   count = count + 1   return count   end   
    end   
    counter = createCounter()   
    print(counter()) -- 返回 1   
    print(counter()) -- 返回 2
    
  6. :表是Lua的核心数据结构,用花括号{}定义。表可以包含键值对,键和值可以是任何数据类型。

    local person = { name = "John", age = 30, hobbies = {"Reading", "Gaming"} }
    print("姓名:" .. person.name)
    print("年龄:" .. person.age)
    
  7. 模块:

    Lua支持模块化编程,允许将相关功能封装在独立的模块中,并通过require关键字加载它们。

  8. 错误处理:

    错误处理通常使用pcall函数来包裹可能引发异常的代码块,以捕获并处理错误。这通常与assert一起使用。

    local success, result = pcall(function()error("出错了!")
    end)if success thenprint("执行成功")
    elseprint("错误信息: " .. result)
    end
    
  9. **标准库:**Lua标准库包含丰富的功能,如文件操作、网络编程、正则表达式、时间处理等。你可以通过内置的模块来使用这些功能,如io、socket等。

  10. 注释:在Lua中,注释是用来为代码添加说明或暂时移除某些代码行的。这对于阅读和维护代码非常有用。Lua支持两种类型的注释:

  • 单行注释:以两个连续的短横线--开始,直到该行结束。所有在--之后的文本都会被Lua解释器忽略。例如:

    -- 这是一个单行注释  
    print("Hello, World!") -- 这里也是注释,但前面的代码会执行`
    
  • 多行注释:使用两个方括号[[开始,并以两个方括号]]结束。在这两个标记之间的所有内容都会被视为注释。例如:

    [[  这是一个多行注释的例子。  你可以在这里写下多行文本,Lua解释器会忽略它。  
    ]]
    

    请注意,多行注释不能嵌套在其他注释或代码块内,因为它的结构是封闭的,像HTML标签一样。

1.4 Lua优势

Lua脚本在Redis中的使用有许多优势,使其成为执行复杂操作的理想选择。以下是一些主要原因:

  • 性能

Lua脚本在Redis中执行,避免了多次的客户端与服务器之间的通信。这可以减少网络开销,提高性能,特别是在需要执行多个Redis命令以完成一个操作时。原子性:Redis保证Lua脚本的原子性执行,无需担心竞态条件或并发问题。

  • 事务

Lua脚本可以与Redis事务一起使用,确保一系列命令的原子性执行。这允许你将多个操作视为一个单一的事务,要么全部成功,要么全部失败。

  • 复杂操作

Lua脚本提供了一种在Redis中执行复杂操作的方法,允许你在一个脚本中组合多个Redis命令。这对于处理复杂的业务逻辑非常有用,例如计算和更新分布式计数器、实现自定义数据结构等。

  • 原子锁

使用Lua脚本,你可以实现复杂的原子锁,而不仅仅是使用Redis的SETNX(set if not exists)命令。这对于分布式锁的实现非常重要。

  • 减少网络开销

对于大批量的数据处理,Lua脚本可以减少客户端和服务器之间的往返次数,从而显著减少网络开销。

  • 减少服务器负载

通过将复杂的计算移至服务器端,可以减轻客户端的负担,降低服务器的负载。

  • 原生支持

Redis天生支持Lua脚本,因此不需要额外的插件或扩展。

  • 可读性和维护性

Lua脚本是一种常见的脚本语言,易于编写和维护。将复杂逻辑封装在脚本中有助于提高代码的可读性。

1.5 Lua语言应用场景

1. 缓存更新

场景:在缓存中存储某些数据,但需要定期或基于条件更新这些数据,同时确保在更新期间不会发生并发问题。

示例:使用Lua脚本,你可以原子性地检查数据的新鲜度,如果需要更新,可以在一个原子性操作中重新计算数据并更新缓存。

local cacheKey = KEYS[1] -- 获取缓存键
local data = redis.call('GET', cacheKey) -- 尝试从缓存获取数据
if not data then-- 数据不在缓存中,重新计算并设置data = calculateData()redis.call('SET', cacheKey, data)
end
return data

2. 原子操作

场景:需要执行多个Redis命令作为一个原子操作,确保它们在多线程或多进程环境下不会被中断。

示例:使用Lua脚本,你可以将多个命令组合成一个原子操作,如实现分布式锁、计数器、排行榜等。

local key = KEYS[1] -- 获取键名
local value = ARGV[1] -- 获取参数值
local current = redis.call('GET', key) -- 获取当前值
if not current or tonumber(current) < tonumber(value) then-- 如果当前值不存在或新值更大,设置新值redis.call('SET', key, value)
end

3. 数据处理:

场景:需要对Redis中的数据进行复杂的处理,如统计、筛选、聚合等。

示例:使用Lua脚本,你可以在Redis中执行复杂的数据处理,而不必将数据传输到客户端进行处理,减少网络开销。

local keyPattern = ARGV[1] -- 获取键名的匹配模式
local keys = redis.call('KEYS', keyPattern) -- 获取匹配的键
local result = {}
for i, key in ipairs(keys) dolocal data = redis.call('GET', key) -- 获取每个键对应的数据-- 处理数据并添加到结果中table.insert(result, processData(data))
end
return result

4. 分布式锁:

场景:实现分布式系统中的锁机制,确保只有一个客户端可以执行关键操作。

示例:使用Lua脚本,你可以原子性地尝试获取锁,避免竞态条件,然后在完成后释放锁。

local lockKey = KEYS[1] -- 获取锁的键名
local lockValue = ARGV[1] -- 获取锁的值
local lockTimeout = ARGV[2] -- 获取锁的超时时间
if redis.call('SET', lockKey, lockValue, 'NX', 'PX', lockTimeout) then-- 锁获取成功,执行关键操作-- ...redis.call('DEL', lockKey) -- 释放锁return true
elsereturn false -- 无法获取锁

这些场景只是Lua脚本在Redis中的应用之一。Lua脚本允许你在Redis中执行更复杂的操作,而无需进行多次的网络通信,从而提高性能和可伸缩性,同时确保数据的一致性和原子性。这使得Lua成为Redis的强大工具,用于处理各种分布式系统需求。

1.6 比较其他脚本语言

Lua语言与一些其他流行的脚本语言(如Python和JavaScript)相比有其独特之处。Python和JavaScript等语言具有更广泛的用途和更庞大的社区支持,而Lua则以其简洁的语法和高效的性能在某些领域占据优势。在游戏开发方面,Lua的轻量级特性和与C++的紧密集成使其成为首选语言。而在Web开发领域,Python和JavaScript因其丰富的库支持和广泛的应用而更为流行。

2. SpringBoot使用Lua脚本

Spring Boot 使用 Lua 作为脚本语言的过程涉及到几个关键步骤。这里是一个简单的示例,展示了如何在 Spring Boot 项目中使用 Lua。

2.1 添加依赖

首先,确保你的 pom.xmlbuild.gradle 文件中包含了必要的依赖。对于 Spring Boot 与 Lua 的集成,你可能需要添加一个 Lua 脚本引擎的依赖,如 luaj

Maven 示例

<dependency>  <groupId>org.luaj</groupId>  <artifactId>luaj-jse</artifactId>  <version>3.0.2</version>  
</dependency>

Gradle 示例

implementation 'org.luaj:luaj-jse:3.0.2'

2.2 配置脚本引擎

接下来,配置一个脚本引擎来执行 Lua 代码。你可以创建一个配置类并使用 @Bean 注解来定义一个 LuaScriptEngine。

配置类示例

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.luaj.vm.LuaValue;  
import org.luaj.vm.lib.jse.JsePlatform;  
import javax.script.ScriptEngine;  
import javax.script.ScriptEngineManager;  
import javax.script.ScriptException;  @Configuration  
public class LuaConfig {  @Bean(name = "luaScriptEngine")  public ScriptEngine luaScriptEngine() throws ScriptException {  ScriptEngineManager manager = new ScriptEngineManager();  ScriptEngine engine = manager.getEngineByName("lua");  JsePlatform.standardGlobals(engine); // Initialize standard globals like _G, etc.  return engine;  }  
}

2.3 使用脚本引擎执行Lua脚本字符串

一旦你已经配置了 Lua 脚本引擎,你可以在 Spring Boot 应用中注入并使用它来执行 Lua 代码。下面是一个简单的控制器示例,它使用 Lua 脚本来处理请求。

Controller 类示例

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
import javax.script.ScriptException;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.http.HttpServletRequest;  
import org.luaj.vm2.*;  
import org.luaj.vm2.lib.*;  
import org.luaj.vm2.lib.jse.*;  @RestController  
public class LuaController {  @Autowired  private ScriptEngine luaScriptEngine;  @GetMapping("/executeLua")  public String executeLua(HttpServletRequest request, HttpServletResponse response) throws ScriptException, IOException {  String luaScript = "return { 'Hello', 'World' }"; // Lua 脚本,这里简单地返回一个数组  JsePlatform jse = JsePlatform.standardGlobals(); // 获取标准全局变量,如 _G 等  LuaValue chunk = jse.load(luaScript); // 加载 Lua 脚本为 chunk  LuaValue result = chunk.call(); // 执行 Lua 脚本并获取结果  Object[] results = (Object[]) result.tovoid(); // 将 LuaValue 转换为 Java 对象数组  return "Lua script executed: " + results[0] + ", " + results[1]; // 返回结果字符串  }  
}

2.4 使用脚本引擎执行Lua脚本文件

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
import javax.script.ScriptException;  
import java.io.IOException;  
import java.io.PrintWriter;  
import javax.servlet.*;  
import javax.servlet.http.*;  
import org.luaj.vm2.*;  
import org.luaj.vm2.*;  
import org.*;@RestController  
public class LuaController {  @Autowired  private ScriptEngine luaScriptEngine;  @GetMapping("/runLua")  public String runLuaScript() throws ScriptException, IOException {  // 读取Lua脚本文件  String luaScriptPath = "path/to/lua/script.lua";  String luaScriptContent = new String(Files.readAllBytes(Paths.get(luaScriptPath)));  // 执行Lua脚本  luaScriptEngine.eval(luaScriptContent);  // 获取Lua脚本的返回结果  PrintWriter out = new PrintWriter(System.out);  ((Invocable) luaScriptEngine).invokeFunction("main", out);  out.flush();  // 返回执行结果  return "Lua脚本执行完成";  }  
}

2.5 SpringBoot使用Lua提高性能

使用Lua脚本可以显著提高Spring Boot应用程序的性能,尤其是在与Redis交互方面。以下是如何使用Lua脚本来实现性能优化的几种方法:

1. 减少网络开销:

  • Redis是内存数据库,数据存储在内存中,而网络通信通常是Redis操作的性能瓶颈之一。通过使用Lua脚本,你可以将多个操作组合成一个原子操作,从而减少了多次的网络往返次数。这对于需要执行多个Redis命令以完成一个操作的情况非常有用。

2. 原子操作:

  • Lua脚本的执行是原子的,这意味着在Lua脚本执行期间,没有其他客户端可以插入其他操作。这使得Lua脚本在实现诸如分布式锁、计数器、排行榜等需要原子操作的情况下非常有用。

例如,考虑一个计数器的场景,多个客户端需要原子性地增加计数。使用Lua脚本,你可以实现原子递增:

local key = KEYS[1]
local increment = ARGV[1]
return redis.call('INCRBY', key, increment)

3. 复杂操作:

  • Lua脚本允许你在Redis服务器端执行复杂的数据处理。这减少了将数据传输到客户端进行处理的开销,并允许你在Redis中执行更复杂的逻辑,从而提高性能。

例如,你可以使用Lua脚本来处理存储在多个键中的数据并返回聚合结果:

local total = 0
for _, key in ipairs(KEYS) dolocal value = redis.call('GET', key)total = total + tonumber(value)
end
return total

4. 事务:

  • 与Lua脚本一起使用事务可以确保一系列Redis命令的原子性执行。这对于需要一组操作要么全部成功,要么全部失败的情况非常重要。

例如,你可以使用Lua脚本在事务中执行一系列更新操作,如果其中一个操作失败,整个事务将回滚:

local key1 = KEYS[1]
local key2 = KEYS[2]
local value = ARGV[1]redis.call('SET', key1, value)
redis.call('INCRBY', key2, value)-- 如果这里的任何一步失败,整个事务将回滚

2.6 错误处理和安全性

处理Lua脚本中的错误和确保安全性在与Redis交互时非常重要。以下是如何处理这些问题的一些建议:

错误处理

  • 错误返回值: Lua脚本在执行期间可能会遇到错误,例如脚本本身存在语法错误,或者在脚本中的某些操作失败。Redis执行Lua脚本后,会返回脚本的执行结果。你可以检查这个结果以查看是否有错误,通常返回值是一个特定的错误标识。例如,如果脚本执行成功,返回值通常是OK,否则会有相应的错误信息。
  • 异常处理: 在Spring Boot应用程序中,你可以使用异常处理来捕获Redis执行脚本时可能抛出的异常。Spring Data Redis提供了一些异常类,如RedisScriptExecutionException,用于处理脚本执行期间的错误。你可以使用try-catch块来捕获这些异常并采取相应的措施,例如记录错误信息或执行备用操作。

安全性

  • 参数验证: 在执行Lua脚本之前,始终验证传递给脚本的参数。确保参数是合法的,并且不包含恶意代码。避免将不受信任的用户输入直接传递给Lua脚本,因为它可能包含恶意的Lua代码。
  • 限制权限: 在Redis服务器上配置适当的权限,以限制对Lua脚本的执行。确保只有授权的用户能够执行脚本,并且不允许执行具有破坏性或不安全操作的脚本。
  • 白名单: 如果你允许动态加载Lua脚本,确保只有受信任的脚本可以执行。你可以创建一个白名单,只允许执行白名单中的脚本,防止执行未经审核的脚本。
  • 沙盒模式: 一些Redis客户端库支持将Lua脚本运行在沙盒模式下,以限制其访问和执行权限。在沙盒模式下,脚本无法执行危险操作,如文件访问。
  • 监控日志: 记录Redis执行Lua脚本的相关信息,包括谁执行了脚本以及执行的脚本内容。这有助于跟踪执行情况并发现潜在的安全问题。

3. 总结

Spring Boot通过集成Redis和Lua,提供了一种高效、可靠的方式来构建现代化的应用程序。Redis作为高性能的内存数据存储,为应用程序提供了快速的数据访问和缓存功能,从而提高了系统的性能和响应速度。而Lua脚本语言则提供了灵活的脚本执行能力,可以在应用程序中实现复杂的业务逻辑和计算任务。通过Spring Boot的集成,开发者可以轻松地使用Redis和Lua来构建高效、可扩展的应用程序,同时简化了开发和维护过程。使用Spring Boot结合Redis和Lua可以为企业级应用程序带来更高的性能、可靠性和灵活性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/655821.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计网Lesson11 - 虚拟机网络环境及socket概述

文章目录 虚拟机的简述socket概述 虚拟机的简述 放张图在这&#xff0c;根本没明白是啥对啥&#xff0c;以后学了Linux再来吧 &#x1f626; socket概述 s o c k e t socket socket 是一种用于应用层的用户态与应用层以下的内核态交互的工具&#xff0c;本意为“插座”。 也就是…

MySQL常用关键字

MySQL常用关键字 目录 MySQL常用关键字DDL关键字DML关键字DQL关键字DCL关键字约束关键字 DDL关键字 DDL关键字含义CREATE TABLE创建一个新的数据库表ALTER TABLE修改现有数据库表的结构或属性DROP TABLE删除数据库中的表MODIFY COLUMN修改列ADD COLUMN新增列CREATE INDEX创建索…

HarmonyOS NEXT 星河版项目案例

参考代码&#xff1a;HeimaHealthy: 鸿蒙项目案例练习 (gitee.com) 1.欢迎页面 Entry Component struct WelcomePage {State message: string Hello Worldbuild() {Column({space: 10}) {Row() {// 1.中央slogonImage($r(app.media.home_slogan)).width(260)}.layoutWeight(…

FL Studio21.2.2中文完整版 适合专业创作者

FL Studio 简称FL&#xff0c;全称&#xff1a;Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前版本是FL Studio2024&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破想…

GD32F30x SPI转CAN 从机实现

SPI 转CAN 目前常用MCP251x 年代较远&#xff0c;目前多数MCU 自带CAN 模块和SPI 主从模块&#xff0c;很方便实现SPI 转CAN 串口等外设&#xff0c;可用作linux 主机下的一个驱动外设&#xff1b; SPI通信不同于串口等全双工通信&#xff0c;主机在发送数据的同时也能得到从机…

分布式虚拟文件系统,如何实现多种存储系统的融合

随着大数据技术和人工智能技术的发展&#xff0c;各种框架应运而生&#xff0c;比如大数据领域中的MapReduce和Spark&#xff0c;人工智能领域中的TensorFlow和PyTorch等。为了给不同的计算框架提供存储服务&#xff0c;存储的服务类型也是很多&#xff0c;常见的如AWS的S3存储…

winform工具报错处理

winform工具报错处理 如图&#xff1a; 出现这种错误&#xff0c;工具打不开就是没有这个&#xff08;.NET&#xff09;环境&#xff0c;需要根据工具的使用开发环境安装配置插件 解决方案 需要安装如图的插件&#xff1a; 选择文件导入报错 1.如果之前已安装过AccessDat…

【c++】日期类的实现-Class Date

代码实现 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; class Date { public:// 获取某年某月的天数int GetMonthDay(int year, int month){static int monteDays[13] { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month 2 &&…

Properties 文件顺序读取问题

我们通常会使用 Properties 去读取 properties 文件的内容&#xff0c;但 Properties 的问题是无法按照 properties 文件的顺序去读取。因为 Properties 继承自Hashtable&#xff0c;是一个基于哈希表的数据结构&#xff0c;元素的存储位置是通过元素的键的哈希值计算出来的&am…

[React源码解析] Fiber (二)

在React15及以前, Reconciler采用递归的方式创建虚拟Dom, 但是递归过程不可以中断, 如果组件的层级比较深的话, 递归会占用线程很多时间, 那么会造成卡顿。 为了解决这个问题, React16将递归的无法中断的更新重构为异步的可中断更新, Fiber架构诞生。 文章目录 1.Fiber的结构2…

Android Studio项目——TCP客户端

目录 一、TCP客户端UI 1、UI展示 2、xml代码 二、TCP客户端数据发送 三、TCP客户端数据接收 一、TCP客户端UI 1、UI展示 2、xml代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.…

【LeetCode】617. 合并二叉树(简单)——代码随想录算法训练营Day20

题目链接&#xff1a;617. 合并二叉树 题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。…

开始一个vue项目

一、新建项目 用cmd命令创建项目 1.1创建文件 以管理员身份打开命令行界面&#xff0c;进入任意一个想要创建项目的文件夹 输入&#xff1a;vue create vue01 1.2创建成功 Successfully created project vue01出现这个说明创建成功1.3项目目录 二、 vue-router 安装和配置的…

C语言-动态内存申请

一、动态分配内存的概述 在数组一章中&#xff0c;介绍过数组的长度是预先定义好的&#xff0c;在整个程序中固定不变&#xff0c;但是在实际的编程中&#xff0c;往往会发生这种情况&#xff0c;即所需的内存空间取决于实际输入的数据&#xff0c;而无法预先确定 。为了解决…

ChatGPT PLUS升级步骤--支付宝、微信

AI伴随着我们已经有一年多了&#xff0c;这一年多里我使用ChatGPT做ppt、生成绘画、写文案、做旅游攻略&#xff0c;还有一些医学知识&#xff0c;医学知识我感觉没有回答的很好&#xff0c;对比于医生给的建议我个人觉得还是医生的比较好&#xff0c;Chat GPT回答的比较官方 …

AWS免费套餐——云存储S3详解

文章目录 前言一、为什么选择S3二、费用估算三、创建S3云存储注册账户登录账户创建存储桶关于官网相关文档 总结 前言 不论个人还是企业&#xff0c;日常开发中经常碰到需要将文档、安装包、日志等文件数据存储到服务器的需求。往常最常用的是云服务器&#xff0c;但是仅仅承担…

leetcode hot100跳跃游戏Ⅱ

本题和上一题还是有不一样的地方&#xff0c;这个题中&#xff0c;我们需要记录我们跳跃的步数并尽可能的满足最小的跳跃步数到达终点。 那么我们还是采用覆盖范围的概念&#xff0c;但是我们需要两个&#xff0c;一个是在当前位置的覆盖范围&#xff0c;另一个是下一步的覆盖…

gerrit 2 升级到 3最新版本(2.16-->3.9.1)--官方升级方式

root用户安装jdk11 和 17 # 11.0.21 支持到gerrit 3.8&#xff0c;gerrit 3.9 得需要 17 [rootlocalhost ~]# cd /usr/local/java/ [rootlocalhost java]# wget https://mirrors.xingyunkeji.com/package/jdk/openjdk-11.0.21%2B9-linux-x64.tar.gz [rootlocalhost java]# wge…

分布式系统面试的秘籍:深入探讨事务、幂等性和补偿事务,掌握二/三阶段提交,了解Sagas事务模型和分布式ID的实战应用!

1、分布式幂等性如何设计&#xff1f;并举例说明 设计分布式系统的幂等性是确保在面对重复请求或操作时系统能够产生相同结果的重要方面。以下是一些设计方法&#xff0c;并结合一个简单的例子说明&#xff1a; 设计方法&#xff1a; 唯一标识符&#xff08;ID&#xff09;:…

网络爬虫详解

网络爬虫&#xff08;Web Crawler&#xff09;是一种自动化程序&#xff0c;用于在互联网上获取和提取数据。它们可以遍历互联网上的网页、收集数据&#xff0c;并进行处理和分析。网络爬虫也被称为网络蜘蛛、网络机器人等。 网络爬虫的工作原理主要是通过模拟浏览器的行为&…