Redis-README官方入门文档

文章目录

    • Redis是什么?
    • 什么是Redis社区版?
    • 构建Redis
    • 修复依赖项或缓存构建选项的构建问题
    • 修复构建32位二进制文件的问题
    • 分配器
    • 单调时钟
    • 详细构建
    • 运行Redis
    • 运行支持TLS的Redis
    • 玩转Redis
    • 安装Redis
    • 代码贡献
    • Redis商标
    • Redis内部结构
    • 源代码布局
    • server.h
    • server.c
    • commands.c
    • networking.c
    • aof.c和rdb.c
    • db.c
    • object.c
    • replication.c
    • 脚本
    • 其他C文件
    • Redis命令的剖析


这个README只是一个快速的入门文档。您可以在redis.io找到更详细的文档。


Redis是什么?

Redis通常被称为一个数据结构服务器。这意味着Redis通过一组命令提供对可变数据结构的访问,这些命令使用TCP套接字和简单协议的服务器-客户端模型发送。因此,不同的进程可以以共享方式查询和修改相同的数据结构。

Redis中实现的数据结构有一些特殊属性:

  • Redis会将它们存储在磁盘上,即使它们总是在服务器内存中被服务和修改。这意味着Redis速度快,但同时也是非易失性的。
  • 数据结构的实现强调内存效率,因此Redis中的数据结构可能比使用高级编程语言建模的相同数据结构使用更少的内存。
  • Redis提供了一些在数据库中自然可以找到的特性,如复制、可调级别的持久性、集群和高可用性。

另一个好的例子是将Redis视为memcached的一个更复杂的版本,其中的操作不仅仅是SET和GET,还包括与列表、集合、有序数据结构等复杂数据类型一起工作的操作。

如果您想了解更多,这是一个精选的起点列表:

  • Redis数据类型介绍。https://redis.io/topics/data-types-intro
  • 在浏览器中直接尝试Redis。https://try.redis.io
  • Redis命令的完整列表。https://redis.io/commands
  • 官方Redis文档中有更多的内容。https://redis.io/documentation

什么是Redis社区版?

Redis OSS在7.4版本发布时更名为Redis社区版(CE)。

Redis Ltd.还提供了Redis软件,这是一个自管理软件,为企业扩展提供了额外的合规性、可靠性和弹性,以及Redis云,这是一个与Google Cloud、Azure和AWS集成的完全托管服务,适用于生产就绪的应用程序。

更多关于Redis社区版和Redis之间差异的信息,请点击这里。

构建Redis

Redis可以在Linux、OSX、OpenBSD、NetBSD、FreeBSD上编译和使用。我们支持大端和小端架构,以及32位和64位系统。

它可能可以在基于Solaris的系统(例如SmartOS)上编译,但我们对这一平台的支持是尽力而为,Redis不能保证在Linux、OSX和*BSD上工作得一样好。

构建过程非常简单:

```
% make
```

要构建支持TLS的Redis,您需要OpenSSL开发库(例如Debian/Ubuntu上的libssl-dev),然后运行:

```
% make BUILD_TLS=yes
```

要构建支持systemd的Redis,您需要systemd开发库(例如Debian/Ubuntu上的libsystemd-dev或CentOS上的systemd-devel),然后运行:

```
% make USE_SYSTEMD=yes
```

要在Redis程序名后追加后缀,请使用:

```
% make PROG_SUFFIX="-alt"
```

您可以使用以下命令构建32位Redis二进制文件:

```
% make 32bit
```

构建Redis后,最好使用以下命令进行测试:

```
% make test
```

如果构建了TLS,可以在启用TLS的情况下运行测试(您需要安装tcl-tls):

```
% ./utils/gen-test-certs.sh
% ./runtest --tls
```

修复依赖项或缓存构建选项的构建问题

Redis有一些依赖项,这些依赖项包含在deps目录中。make命令不会自动重新构建依赖项,即使依赖项的源代码发生了变化。

当您使用git pull更新源代码或以其他方式修改依赖项树中的代码时,请确保使用以下命令真正清理一切并从头开始重建:

```
% make distclean
```

这将清理:jemalloc、lua、hiredis、linenoise等依赖项。

此外,如果您强制某些构建选项,如32位目标、无C编译器优化(用于调试目的)等类似的构建时选项,这些选项会无限期地缓存,直到您发出make distclean命令。

修复构建32位二进制文件的问题

如果您在以32位目标构建Redis后需要用64位目标重新构建它,或者反过来,您需要在Redis发行版的根目录执行make distclean

在尝试构建Redis的32位二进制文件时,如果遇到构建错误,请尝试以下步骤:

  • 安装libc6-dev-i386软件包(也尝试g+±multilib)。
  • 尝试使用以下命令行代替make 32bit
    make CFLAGS="-m32 -march=native" LDFLAGS="-m32"
    

分配器

在构建Redis时选择非默认内存分配器是通过设置MALLOC环境变量来完成的。Redis默认使用libc malloc进行编译和链接,但在Linux系统上,默认使用jemalloc。选择这个默认值是因为jemalloc被证明比libc malloc有更少的碎片问题。

要强制使用libc malloc进行编译,请使用:

```
% make MALLOC=libc
```

在Mac OS X系统上使用jemalloc进行编译,请使用:

```
% make MALLOC=jemalloc
```

单调时钟

默认情况下,Redis将使用POSIX clock_gettime函数作为单调时钟源。在大多数现代系统上,可以使用内部处理器时钟来提高性能。警告信息可以在这里找到。

要构建支持处理器内部指令时钟的Redis,请使用:

```
% make CFLAGS="-DUSE_PROCESSOR_CLOCK"
```

详细构建

Redis默认会以用户友好的彩色输出进行构建。如果您想看到更详细的输出,请使用以下命令:

```
% make V=1
```

运行Redis

要使用默认配置运行Redis,只需输入:

```
% cd src
% ./redis-server
```

如果您想提供自己的redis.conf,您必须使用额外的参数(配置文件的路径)来运行它:

```
% cd src
% ./redis-server /path/to/redis.conf
```

可以通过直接将参数作为选项使用命令行来更改Redis配置。示例:

```
% ./redis-server --port 9999 --replicaof 127.0.0.1 6379
% ./redis-server /etc/redis/6379.conf --loglevel debug
```

redis.conf中的所有选项也支持作为命令行选项使用,名称完全相同。

运行支持TLS的Redis

有关如何使用TLS运行Redis的更多信息,请参考TLS.md文件。

玩转Redis

您可以使用redis-cli来玩转Redis。启动一个redis-server实例,然后在另一个终端尝试以下操作:

```
% cd src
% ./redis-cli
redis> ping
PONG
redis> set foo bar
OK
redis> get foo
"bar"
redis> incr mycounter
(integer) 1
redis> incr mycounter
(integer) 2
```

您可以在https://redis.io/commands找到所有可用命令的列表。

安装Redis

要将Redis二进制文件安装到/usr/local/bin,只需使用:

```
% make install
```

如果您希望使用不同的目的地,可以使用make PREFIX=/some/other/directory install

make install只会在系统中安装二进制文件,但不会在适当位置配置init脚本和配置文件。如果您只是想尝试一下Redis,这并不需要,但如果您要为生产系统正确安装它,我们有一个脚本来为Ubuntu和Debian系统执行此操作:

```
% cd utils
% ./install_server.sh
```

注意install_server.sh在Mac OSX上不起作用;它仅适用于Linux。

该脚本会问您几个问题,并为您设置一切所需,以便Redis可以作为后台守护进程正确运行,并在系统重启时再次启动。

您将能够使用名为/etc/init.d/redis_<portnumber>的脚本停止和启动Redis,例如/etc/init.d/redis_6379

代码贡献

通过以任何形式向Redis项目贡献代码,包括通过GitHub发送拉取请求、通过私人电子邮件或公共讨论组发送代码片段或补丁,您同意根据Redis软件授权和贡献者许可协议发布您的代码。Redis软件包含对原始Redis核心项目的贡献,这些贡献归其贡献者所有,并在3BSD许可下授权。此存储库中的任何该许可的副本仅适用于这些贡献。Redis从7.4.x版本及以后的所有Redis社区版版本均在LICENSE.txt文件中描述的RSALv2/SSPL双许可下发布。

有关更多信息,请参见此源分发中的CONTRIBUTING.md文件。有关安全漏洞和漏洞,请参阅SECURITY.md。

Redis商标

商标的目的是标识个人或公司的货物和服务,以免造成混淆。作为其名称和标志的注册所有者,Redis接受其商标的某些有限使用,但必须遵循其在商标指南中描述的要求。

Redis内部结构

如果您正在阅读此README,您可能正面对一个GitHub页面,或者您刚刚解压缩了Redis发行版tar球。在这两种情况下,您基本上离源代码只有一步之遥,因此这里我们解释Redis源代码布局、每个文件中的内容以及Redis服务器中的最重要功能和结构等。我们保持所有讨论都在高层次上,不深入细节,因为否则这份文件会非常大,而且我们的代码库不断变化,但一个总体概念应该是一个良好的起点,以便更多地了解。此外,大部分代码都有详细的注释,易于理解。

源代码布局

Redis根目录仅包含此README、调用src目录中真实Makefile的Makefile以及Redis和Redis Sentinel的示例配置。您可以找到一些用于执行Redis、Redis集群和Redis Sentinel单元测试的shell脚本,这些测试在tests目录中实现。

根目录中包含以下重要目录:

  • src:包含用C语言编写的Redis实现。
  • tests:包含用Tcl实现的单元测试。
  • deps:包含Redis使用的库。编译Redis所需的一切都在这个目录中;您的系统只需要提供libc、POSIX兼容接口和C编译器。值得注意的是,deps包含一份jemalloc的副本,这是Linux下Redis的默认分配器。请注意,在deps下还有一些从Redis项目开始但主存储库不是redis/redis的东西。

还有一些其他的目录,但它们对我们的目标来说并不重要。我们将主要关注src,Redis实现包含在其中,探索每个文件中的内容。文件暴露的顺序是逻辑上的,以便逐步揭示不同层次的复杂性。

注意:最近Redis被重构了很多。函数名和文件名已经更改,所以您可能会发现这份文档更接近unstable分支。例如,在Redis 3.0中,server.cserver.h文件被命名为redis.credis.h。但总体结构是相同的。请记住,所有的新开发和拉取请求都应该针对unstable分支。

server.h

理解程序如何工作最简单的方法是理解它使用的数据结构。因此,我们将从Redis的主头文件server.h开始。

所有服务器配置和一般所有共享状态都定义在一个名为server的全局结构中,类型为struct redisServer。这个结构中的一些重要字段是:

  • server.db是Redis数据库的数组,数据存储在这里。
  • server.commands是命令表。
  • server.clients是连接到服务器的客户端的链表。
  • server.master是一个特殊的客户端,主节点,如果实例是副本。

还有很多其他字段。大多数字段都在结构定义中直接注释。

另一个重要的Redis数据结构是定义客户端的结构。
过去它被称为redisClient,现在只是client。该结构有很多字段,这里我们只展示主要的:

struct client {int fd;sds querybuf;int argc;robj **argv;redisDb *db;int flags;list *reply;// ...很多其他字段...char buf[PROTO_REPLY_CHUNK_BYTES];
}

客户端结构定义了一个连接的客户端

  • fd字段是客户端套接字文件描述符。
  • argcargv用客户端正在执行的命令填充,以便实现特定Redis命令的函数可以读取参数。
  • querybuf累积来自客户端的请求,这些请求由Redis服务器根据Redis协议解析并执行客户端正在执行的命令。
  • replybuf是动态和静态缓冲区,累积服务器发送给客户端的回复。这些缓冲区一旦文件描述符可写,就会逐步写入套接字。

正如您在上述客户端结构中看到的,命令中的参数被描述为robj结构。以下是完整的robj结构,它定义了一个Redis对象

struct redisObject {unsigned type:4;unsigned encoding:4;unsigned lru:LRU_BITS; /* LRU时间(相对于全局lru_clock)或* LFU数据(最低有效8位频率* 和最高有效16位访问时间)。 */int refcount;void *ptr;
};

基本上,这个结构可以表示所有基本的Redis数据类型,如字符串、列表、集合、有序集合等。有趣的事情是它有一个type字段,这样我们就可以知道给定对象的类型,还有一个refcount,这样同一个对象就可以在多个地方被引用,而不需要多次分配。最后,ptr字段指向对象的实际表示,这可能即使对于同一类型,也会根据使用的encoding而异。

Redis对象在Redis内部广泛使用,但为了避免间接访问的开销,最近在许多地方我们只是使用没有包装在Redis对象中的普通动态字符串。

server.c

这是Redis服务器的入口点,定义了main()函数。以下是启动Redis服务器的最重要步骤。

  • initServerConfig()设置server结构的默认值。
  • initServer()分配所需的数据结构,设置监听套接字等。
  • aeMain()启动事件循环,监听新连接。

事件循环会定期调用两个特殊函数:

  1. serverCron()定期调用(根据server.hz频率),执行必须不时执行的任务,如检查超时的客户端。
  2. beforeSleep()每次事件循环触发,Redis服务了一些请求,并返回到事件循环时调用。

在server.c中,您可以找到处理Redis服务器其他重要事项的代码:

  • call()用于在给定客户端的上下文中调用给定命令。
  • activeExpireCycle()处理通过EXPIRE命令设置的具有生存时间的键的驱逐。
  • performEvictions()在应该执行新的写命令但Redis根据maxmemory指令内存不足时调用。
  • 全局变量redisCommandTable定义了所有Redis命令,指定了命令的名称、实现命令的函数、所需的参数数量以及每个命令的其他属性。

commands.c

这个文件是由utils/generate-command-code.py自动生成的,内容基于src/commands文件夹中的JSON文件。
这些应该是关于Redis命令的唯一真相来源,以及它们的所有元数据。
这些JSON文件不打算被任何人直接使用,而是可以通过COMMAND命令获得元数据。

networking.c

这个文件定义了与客户端、主节点和副本(在Redis中只是特殊客户端)的所有I/O函数:

  • createClient()分配并初始化一个新客户端。
  • addReply*()系列函数由命令实现用来向客户端结构追加数据,这些数据将作为对给定执行命令的回复传输给客户端。
  • writeToClient()将输出缓冲区中的数据传输给客户端,并由可写事件处理器sendReplyToClient()调用。
  • readQueryFromClient()可读事件处理器,并将从客户端读取的数据累积到查询缓冲区。
  • processInputBuffer()是解析客户端查询缓冲区的入口点,根据Redis协议。一旦命令准备好被处理,它调用定义在server.c中的processCommand()来实际执行命令。
  • freeClient()释放、断开连接并移除客户端。

aof.c和rdb.c

正如您从名称中猜测的,这些文件实现了Redis的RDB和AOF持久性。Redis使用基于fork()系统调用的持久性模型,以创建一个与主Redis进程具有相同(共享)内存内容的进程。这个辅助进程将内存内容转储到磁盘上。这被rdb.c用来在磁盘上创建快照,以及aof.c用来在追加文件变得太大时执行AOF重写。

aof.c中的实现还有额外的函数,以便实现一个API,允许命令在客户端执行时将新命令追加到AOF文件中。

server.c中定义的call()函数负责调用函数,这些函数反过来将命令写入AOF。


解释:

这段话描述的是Redis数据库的持久性机制,具体来说,是如何通过操作系统的fork()系统调用来实现数据的持久化。下面是对这段话的详细解释:

  1. 基于fork()系统调用的持久性模型
    • Redis使用fork()系统调用来创建一个新的进程,这个新进程是主Redis进程的一个副本,它们共享相同的内存空间。这种机制允许Redis在不干扰主进程处理客户端请求的情况下,进行数据持久化操作。
    • fork() 是一个在 Unix 和类 Unix 操作系统中使用的系统调用,它用于创建一个新的进程,称为子进程,这个子进程是调用 fork() 的原始进程(父进程)的一个副本。这个系统调用的特点是它在父进程中返回子进程的进程ID,在子进程中返回0。

简单来说,fork() 函数的作用是复制当前进程,创建一个新的进程,这个新进程几乎与原进程完全相同,包括代码段、数据段和堆栈等。这使得 fork() 在多进程编程中非常有用,尤其是在需要并行处理任务或者创建守护进程时。

fork() 调用之后,父进程和子进程将从 fork() 调用之后的代码点继续执行,但它们将有不同的进程ID,并且可以独立地执行不同的代码路径。这允许父进程和子进程执行不同的任务,或者子进程可以执行特定的任务而不影响父进程。

  1. 创建具有相同(共享)内存内容的进程

    • 当Redis执行fork()操作时,它会创建一个子进程,这个子进程拥有与父进程(主Redis进程)相同的内存内容。这意味着子进程可以访问父进程的所有数据,包括内存中的数据结构。
  2. 辅助进程将内存内容转储到磁盘上

    • 这个子进程(辅助进程)的职责是将内存中的数据转储到磁盘上。这样做的目的是为了在系统发生故障时能够恢复数据,确保数据的持久性。
  3. rdb.c用来在磁盘上创建快照

    • Redis的RDB持久性机制是通过rdb.c这个文件实现的。RDB(Redis Database)是一种将Redis内存中的数据以快照的形式保存到磁盘上的机制。这个快照文件包含了某一时刻Redis数据库的状态,可以在Redis重启时用来恢复数据。
  4. aof.c用来在追加文件变得太大时执行AOF重写

    • AOF(Append Only File)是Redis的另一种持久性机制,它通过记录每次写操作来保存数据变更。随着时间的推移,AOF文件可能会变得非常大,这可能会影响Redis的性能。aof.c文件实现了AOF重写功能,它可以创建一个新的AOF文件,只包含恢复数据所需的最小命令集,从而减小AOF文件的大小。

总结来说,这段话描述了Redis如何通过fork()系统调用来创建一个辅助进程,这个进程负责将内存中的数据持久化到磁盘上,以实现数据的快照保存(RDB)和AOF文件的重写,从而保证数据的持久性和一致性。


“堆栈”(stack)是计算机内存中的一个区域,用于存储程序运行时的临时数据。它是一种特殊的数据结构,遵循后进先出(LIFO,Last In First Out)的原则,即最后添加到堆栈的数据会最先被移除。堆栈在程序执行过程中扮演着重要的角色,主要功能包括:

  1. 函数调用和返回:当程序调用一个函数时,相关的返回地址和局部变量会被压入堆栈中。当函数执行完毕后,堆栈会弹出这些信息,以便程序能够返回到正确的位置继续执行。

  2. 局部变量存储:函数内部定义的局部变量通常存储在堆栈中。

  3. 表达式求值:在计算表达式时,中间结果可能会被存储在堆栈中。

  4. 异常处理:当程序抛出异常时,异常处理相关的信息也会被存储在堆栈中。

在多进程编程中,fork() 函数创建的新进程会复制父进程的堆栈,这意味着新进程会继承父进程在堆栈中的所有数据,包括局部变量和函数调用的上下文信息。这对于进程间的信息传递和任务的并行处理非常重要。

“堆栈”这个术语在计算机科学中有两种不同的含义,它们分别对应于数据结构和内存管理两个领域:

  1. 数据结构中的栈(Stack)

    • 在数据结构中,栈是一种线性数据结构,遵循后进先出(LIFO)的原则。这意味着最后添加的元素将是第一个被移除的元素。
    • 栈的基本操作通常包括push(入栈,添加元素到栈顶)和pop(出栈,移除栈顶元素)。
    • 栈常用于解决需要回溯的问题,如函数调用栈、括号匹配、表达式求值等。
  2. 内存管理中的堆栈(Heap and Stack)

    • 在内存管理中,"堆栈"通常指的是两个不同的区域:堆(Heap)和栈(Stack)。
    • 栈(Stack):如前所述,用于存储程序运行时的临时数据,如函数调用的上下文信息、局部变量等,遵循LIFO原则。
    • 堆(Heap):用于动态内存分配,程序可以在运行时请求任意大小的内存块,并在使用完毕后释放。堆不遵循特定的顺序原则,它允许在任何位置添加和移除元素,但通常需要手动管理内存(分配和释放)。

所以,当提到“堆栈”时,如果是在讨论数据结构,那么它指的是栈;如果是在讨论内存管理,那么它可能指的是堆和栈两个不同的概念。在上下文中,需要根据具体语境来确定“堆栈”指的是哪一个。


db.c

某些Redis命令操作特定数据类型;其他是通用的。
通用命令的例子是DELEXPIRE。它们操作键而不是具体值。所有这些通用命令都定义在db.c中。

此外,db.c实现了一个API,以便在不直接访问内部数据结构的情况下对Redis数据集执行某些操作。

db.c中许多命令实现中使用的最重要的函数如下:

  • lookupKeyRead()lookupKeyWrite()用于获取与给定键关联的值的指针,如果键不存在则为NULL
  • dbAdd()及其高级对应setKey()在Redis数据库中创建一个新键。
  • dbDelete()移除一个键及其关联的值。
  • emptyData()移除一个整个数据库或所有定义的数据库。

文件的其余部分实现了暴露给客户端的通用命令。

object.c

定义Redis对象的robj结构已经被描述过。在object.c中,有所有在基本层面上操作Redis对象的函数,如分配新对象、处理引用计数等。此文件中的著名函数:

  • incrRefCount()decrRefCount()用于增加或减少对象的引用计数。当它降到0时,对象最终被释放。
  • createObject()分配一个新对象。还有一些专门分配具有特定内容的字符串对象的专门函数,如createStringObjectFromLongLong()等。

此文件还实现了OBJECT命令。

replication.c

这是Redis中最复杂的文件之一,建议在熟悉代码库的其余部分后再接触它。
在这个文件中,有Redis的主节点和副本角色的实现。

此文件中最重要的函数之一是replicationFeedSlaves(),它将命令写入代表连接到我们主节点的副本实例的客户端,以便副本可以获得客户端执行的写入:
这样它们的数据集将与主节点中的数据集保持同步。

此文件还实现了SYNCPSYNC命令,这些命令用于在主节点和副本之间执行首次同步,或在断开连接后继续复制。

脚本

脚本单元由3个单元组成:

  • script.c - 脚本与Redis的集成(命令执行,设置复制/resp,…)
  • script_lua.c - 负责执行Lua代码,使用script.c在Lua代码内与Redis交互。
  • function_lua.c - 包含Lua引擎实现,使用script_lua.c执行Lua代码。
  • functions.c - 包含Redis函数实现(FUNCTION命令),如果它想要调用的函数需要Lua引擎,则使用functions_lua.c
  • eval.c - 包含使用script_lua.c调用Lua代码的eval实现。

其他C文件

  • t_hash.ct_list.ct_set.ct_string.ct_zset.ct_stream.c包含Redis数据类型的实现。它们实现了访问给定数据类型的API,并实现了这些数据类型的客户端命令。
  • ae.c实现了Redis事件循环,它是一个自包含的库,简单易懂。
  • sds.c是Redis字符串库,更多信息请访问https://github.com/antirez/sds。
  • anet.c是一个库,用于以比内核暴露的原始接口更简单的方式使用POSIX网络。
  • dict.c是一个非阻塞哈希表的实现,它增量地重新哈希。
  • cluster.c实现了Redis集群。可能只有在熟悉了Redis代码库的其余部分之后才值得一读。如果您想阅读cluster.c,请确保阅读Redis Cluster规格。

Redis命令的剖析

所有Redis命令都以以下方式定义:

void foobarCommand(client *c) {printf("%s",c->argv[1]->ptr); /* 对参数进行一些操作。 */addReply(c,shared.ok); /* 向客户端回复一些内容。 */
}

命令函数由JSON文件引用,连同其元数据,详见上述的commands.c
命令标志在server.h中的struct redisCommand上面的注释中记录。
有关其他详细信息,请参阅COMMAND命令。https://redis.io/commands/command/

命令以某种方式操作后,它通常会使用addReply()networking.c中定义的类似函数向客户端返回回复。

在Redis源代码中有大量的命令实现可以作为实际命令实现的示例(例如pingCommand)。编写一些玩具命令可以是熟悉代码库的好练习。

这里没有描述的文件还有很多,但涵盖一切是无用的。我们只想帮助您迈出第一步。
最终,您会找到进入Redis代码库的路:-)

享受吧!


这是翻译后的内容。如果您需要将这个内容保存为新文件,请告知我文件的名称和格式,我将为您生成。

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

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

相关文章

Netty 组件介绍 - Future Promise

在异步处理时&#xff0c;经常用到这两个接口 netty 中的 Future 继承 jdk 中的 FutuFuture&#xff0c;而Promise 又对 netty Future 进行了扩展。 idk Future 只能同步等待任务结束&#xff08;或成功或失败)才能得到结果netty Future 可以同步等待任务结束得到结也可以异…

ai数字人分身123口播克隆数字人小程序源码_博纳软云

功能配置 一、用户 用户管理小黑屋用户反馈登录设置短信参数 二、作品 视频作品背景音乐库背景音乐分类 三、形象分身 上传记录视频要求参数配置 四、声音克隆 克隆记录参数配置声音要求文案示例 五、AI文案 生成记录创作模型模型分类Al配置 六、充值 充值订单积分套…

Elasticsearch Interval 查询:为什么它们是真正的位置查询,以及如何从 Span 转换

作者&#xff1a;来自 Elastic Mayya Sharipova 解释 span 查询如何成为真正的位置查询以及如何从 span 查询过渡到它们。 长期以来&#xff0c;Span 查询一直是有序和邻近搜索的工具。这些查询对于特定领域&#xff08;例如法律或专利搜索&#xff09;尤其有用。但相对较新的 …

软件测试模型

软件测试模型是在软件开发过程中&#xff0c;用于指导软件测试活动的一系列方法和框架。这些模型帮助测试团队确定何时进行测试、测试什么以及如何测试&#xff0c;从而确保软件的质量和稳定性。 一 V模型 V模型是一种经典的软件测试模型,它由瀑布研发模型演变而来的测试模型…

Tiling与流水线技术小结

文章目录 Tiling技术Loop TilingAI推理中的Tiling 参考 流水线技术指令周期 参考 Tiling技术 Tiling&#xff08;平铺&#xff09;是一种将大的问题或数据集分解为较小的子问题或子数据集的技术&#xff0c;目的是提高数据局部性和缓存利用率&#xff0c;从而提升程序性能。 在…

Pinia-状态管理

Pinia-状态管理 特点&#xff1a; 1. 轻量和模块化 Pinia 是一个轻量级的状态管理库&#xff0c;支持模块化管理&#xff0c;即可以将应用的状态分成多个 store 以实现更好的组织。使用 Pinia&#xff0c;可以定义多个 store&#xff0c;每个 store 都是一个独立的模块&#x…

openpnp - 在openpnp中单独测试相机

文章目录 openpnp - 在openpnp中单独测试相机概述笔记测试工装相机镜头顶部盖子到目标的距离END openpnp - 在openpnp中单独测试相机 概述 底部相机的位置不合适, 重新做了零件&#xff0c;准备先确定一下相机和吸嘴的距离是多少才合适。 如果在设备上直接实验&#xff0c;那…

网络模型——二层转发原理

网课地址&#xff1a;网络模型_二层转发原理&#xff08;三&#xff09;_哔哩哔哩_bilibili 一、路由交换 网络&#xff1a;用来信息通信&#xff0c;信息共享的平台。 网络节点&#xff08;交换机&#xff0c;路由器&#xff0c;防火墙&#xff0c;AP&#xff09;介质&#…

[watevrCTF 2019]Voting Machine 1-好久不见10

shiiftF12查找字符串&#xff0c;发现flag.text跟踪 from pwn import * i remote("node5.anna.nssctf.cn",22956) address 0x400807 payload ba*(0x28) p64(address) i.sendline(payload) i.interactive()

【Linux】从零开始使用多路转接IO --- select

碌碌无为&#xff0c;则余生太长&#xff1b; 欲有所为&#xff0c;则人生苦短。 --- 中岛敦 《山月记》--- 从零开始认识五种IO模型 1 前言2 认识多路转接select3 多路转接select等待连接4 完善代码5 总结 1 前言 上一篇文章我们讲解了五种IO模型的基本概念&#xff0c;并…

【Java SE 】String 类 详解!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 1. String 的地位 在Java 编程中&#xff0c;字符串的使用是非常频繁的&#xff0c;而字符串的使用有离不开 String类 &#xff0c;在开发和面试中String类也是非常…

专业130+总400+武汉理工大学855信号与系统考研经验电子信息与通信工程,真题,大纲,参考书。

已经顺利读研一段时间&#xff0c;回顾一下考研还是历历在目。应群里学弟要求&#xff0c;回忆总结一下自己考研经历&#xff0c;希望对大家复习有帮助。总分400&#xff0c;专业课855信号与系统130&#xff08;犯了低级错误&#xff0c;计算出现问题&#xff0c;大家专业好好准…

Self-Lengthen:阿里千问开源提升 LLM 长文本生成能力的训练框架

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

双向链表及如何使用GLib的GList实现双向链表

双向链表是一种比单向链表更为灵活的数据结构&#xff0c;与单向链表相比可以有更多的应用场景&#xff0c;本文讨论双向链表的基本概念及实现方法&#xff0c;并着重介绍使用GLib的GList实现单向链表的方法及步骤&#xff0c;本文给出了多个实际范例源代码&#xff0c;旨在帮助…

C++笔试题之实现一个定时器

一.定时器&#xff08;timer&#xff09;的需求 1.执行定时任务的时&#xff0c;主线程不阻塞&#xff0c;所以timer必须至少持有一个线程用于执行定时任务 2.考虑到timer线程资源的合理利用&#xff0c;一个timer需要能够管理多个定时任务&#xff0c;所以timer要支持增删任务…

【Java笔记】1-JDK/JRE/JVM是个啥?

JDK、JRE、JVM可以说是入门必须了解的三个词汇 先说全称 JDK&#xff1a;Java Development Kit&#xff0c;Java开发工具包 JRE&#xff1a;Java Runtime Environment&#xff0c;Java运行环境 JVM&#xff1a;Java Virtual Machine&#xff0c;Java虚拟机 再说关系 JVM⊆J…

c语言-进位计数制

文章目录 一、进位计数制是什么&#xff1f;二、c语言1.二进制转十进制2.十进制转二进制 一、进位计数制是什么&#xff1f; 进位计数制简称进制&#xff0c;是人类用于计算数量的基本规则。 可使用数字符号的数目称为基数或底数&#xff0c;基数个数为n个&#xff0c;即可称n…

HTML 基础标签——结构化标签<html>、<head>、<body>

文章目录 1. <html> 标签2. <head> 标签3. <body> 标签4. <div> 标签5. <span> 标签小结 在 HTML 文档中&#xff0c;使用特定的结构标签可以有效地组织和管理网页内容。这些标签不仅有助于浏览器正确解析和渲染页面&#xff0c;还能提高网页的可…

【算法赌场】区间合并

区间问题 区间问题的引入 数学上&#xff0c;用两个数字可以确定数轴上的一个区间&#xff0c;较小的数字叫做区间的左端点&#xff0c;也叫区间起点&#xff0c;较大的数字叫做区间的右端点&#xff0c;也叫区间终点。 在算法竞赛中&#xff0c;很多题目是以区间为单位去进行…

给定开始日期时间结束日期时间、间隔得到符合条件的序列pandas.timedelta_range()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 给定开始日期时间 结束日期时间、间隔 得到符合条件的序列 pandas.timedelta_range() [太阳]选择题 以下代码执行后&#xff0c;delta中包含的时间差序列的个数是多少&#xff1f; import pa…