【入门篇】1.4 redis 客户端 之 Lettuce 详解

news2025/1/19 2:59:40

文章目录

  • 1. 简介
    • 1. 什么是Lettuce
    • 2. Lettuce与其他Redis客户端的比较
    • 3. Lettuce的特性和优势
  • 2. 安装和配置
  • 3. 连接池配置
    • 1. 什么是连接池
    • 2. Lettuce的连接池使用与配置
    • 3. 连接池配置项
  • 4. 基本操作
    • 1. 如何创建Lettuce连接
    • 2. Lettuce的基本操作如增删改查
    • 3. Lettuce的事务操作
    • 4. Lettuce的管道操作
    • 5. Lettuce的发布订阅操作
    • 6. Lettuce的脚本执行
  • 5. 错误处理和重试
  • 6. Lettuce vs Jedis
  • 7. 参考资料

在这里插入图片描述

1. 简介

1. 什么是Lettuce

Lettuce是一个高级Redis客户端,用于线程安全的同步、异步和反应式访问。它支持高级的Redis特性,如Sentinel、集群、流水线、自动重新连接和redis数据模型等。Lettuce是完全非阻塞的,基于Netty事件驱动的通信层,其方法将返回具有可观察的类型,可在流或异步编程环境中使用。

2. Lettuce与其他Redis客户端的比较

与Jedis这种阻塞的Java Redis客户端相比,Lettuce的主要优势在于其完全非阻塞的IO和线程安全。使用Jedis,在多线程环境中,需要使用连接池以避免线程安全问题,但是对于Lettuce来说,可以避免这种复杂的设置,因为一个Lettuce连接实例(StatefulRedisConnection)就是线程安全的。另一个重要的区别是,Lettuce支持Redis的高级特性,如集群、流水线、发布订阅、和Lua脚本。

3. Lettuce的特性和优势

  • 完全非阻塞IO和线程安全:Lettuce使用Netty进行网络通信,采用了异步和事件驱动的模型。一个Lettuce连接实例(StatefulRedisConnection)是线程安全的,可以在多个线程间共享。
  • 支持Redis的高级特性:Lettuce支持Redis的高级特性,如Sentinel、集群、流水线、发布订阅、Lua脚本等。
  • 自动重连:Lettuce支持自动重连,当Redis服务器重新启动或断开连接时,Lettuce可以自动恢复连接。
  • 可观察的数据类型:Lettuce的所有操作都返回Observable,这可以让在流或异步编程环境中使用。

2. 安装和配置

在Java项目中,可以使用Maven或者Gradle来引入Lettuce的依赖。

  1. 使用Maven引入依赖
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.1.5.RELEASE</version> <!-- 请将此版本号替换为所需要的版本 -->
</dependency>
  1. 使用Gradle引入依赖
dependencies {
    implementation 'io.lettuce:lettuce-core:6.1.5.RELEASE'  
}

配置Lettuce非常简单
创建一个新的RedisClient实例,使用redis://password@localhost:6379/0作为Redis服务器的URL。然后我们打开一个新的连接,并通过此连接获取同步命令来执行Redis命令。执行完命令后,我们关闭了连接并关闭了Redis客户端。

import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;

public class Example {

    public static void main(String[] args) {

        // 初始化Redis客户端
        RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0");

        // 打开一个新的连接
        StatefulRedisConnection<String, String> connection = redisClient.connect();

        // 获取同步命令
        RedisCommands<String, String> syncCommands = connection.sync();

        // 执行命令
        syncCommands.set("key", "Hello, Redis!");

        // 关闭连接
        connection.close();

        // 关闭Redis客户端
        redisClient.shutdown();
    }
}

3. 连接池配置

1. 什么是连接池

连接池是一个预先创建并存储数据库连接的容器,应用程序在需要与数据库交互时,可以从连接池中获取已经建立的连接。使用完毕后,将该连接归还给连接池,而不是关闭它。这种技术可以避免每次需要与数据库交互时都打开新的连接,节省了创建新连接所需的时间。

Lettuce是一个基于Netty的高级Redis客户端,用于线程安全同步、异步和响应式通信。在Lettuce中,每次发送命令都会获取新的连接,执行完命令后就会关闭。这就是说,Lettuce本身并没有传统意义上的"连接池"。

2. Lettuce的连接池使用与配置

虽然在Lettuce本身并未实现连接池,但是在使用Spring Data Redis的情况下,可以通过配置LettuceConnectionFactory来实现连接池的效果。

以下是一个配置示例:

import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;

// 创建连接池配置
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
    .poolConfig(new GenericObjectPoolConfig())
    .build();

// 创建服务器配置
RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("localhost", 6379);

// 使用这两种配置创建Lettuce连接工厂
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, clientConfig);

在这个配置中,我们使用LettucePoolingClientConfiguration.builder()来创建一个LettuceClientConfiguration的Builder,并使用poolConfig()方法来设置连接池配置。然后,我们使用这个配置和服务器配置来创建一个新的LettuceConnectionFactory

注意,GenericObjectPoolConfig可以让设置一些连接池的参数,例如maxTotal(最大连接数),maxIdle(最多的空闲连接数),minIdle(最少的空闲连接数)等等。

在Lettuce中,使用RedisClient或者RedisClusterClient创建的基本连接实际上是一个连接池。可以通过ClientOptionsClientResources来定制连接池的行为。

默认连接池的行为如下:

  1. 默认情况下,连接池大小为8个连接。
  2. 连接尝试失败后,默认重试时间间隔为30秒。

在创建RedisClient或者RedisClusterClient之前,可以通过ClientResources.Builder来定制连接池的一些参数,如下所示:

import io.lettuce.core.RedisClient;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;

public class Example {

    public static void main(String[] args) {

        // 创建一个ClientResources来定制连接池参数
        ClientResources clientResources = DefaultClientResources.builder()
            .ioThreadPoolSize(16) // IO线程池大小
            .computationThreadPoolSize(16) // 计算线程池大小
            .build();

        // 使用定制的ClientResources来创建RedisClient
        RedisClient redisClient = RedisClient.create(clientResources, "redis://localhost:6379");

        // 其他代码...
    }
}

对于更复杂的需求,如最大连接数、最小空闲连接数等,Lettuce本身并没有提供对应的配置项。Lettuce的设计理念是每个Redis命令都运行在一个独立的连接上,因此并没有传统意义上的“连接池”。可以根据自己的需求,通过控制并发命令的数量来间接控制连接数量。

然而,如果正在使用Spring Data Redis,那么在Spring Data Redis中,可以通过LettucePoolingClientConfiguration来配置连接池(包括最大连接数、最小空闲连接数等),如下所示:

import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;

LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
    .poolConfig(new GenericObjectPoolConfig())
    .build();

RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration("server", 6379);

LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(serverConfig, clientConfig);

在上面的代码中,我们使用LettucePoolingClientConfiguration.builder()来创建一个LettuceClientConfiguration的Builder,并使用poolConfig()方法来设置连接池配置。然后,我们使用这个配置和服务器配置来创建一个新的LettuceConnectionFactory

3. 连接池配置项

配置Lettuce的连接池可以通过LettuceConnectionFactory类来实现。下面是配置连接池的一些常用参数:

  1. 最大连接数(MaxConnections):指定连接池的最大连接数,即同时能够从连接池中获取的最大连接数。可以使用setConnectionPoolConfiguration()方法来设置。
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(maxConnections);
lettuceConnectionFactory.setPoolConfig(poolConfig);
  1. 最小空闲连接数(MinIdleConnections):指定连接池中的最小空闲连接数,即连接池中保持的最少可用连接数。可以使用setPoolConfig()方法来设置。
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMinIdle(minIdleConnections);
lettuceConnectionFactory.setPoolConfig(poolConfig);
  1. 连接空闲超时时间(IdleTimeout):指定连接在空闲状态下的超时时间,超过该时间会被连接池回收。可以使用setTimeout()方法来设置。
lettuceConnectionFactory.setTimeout(idleTimeout);
  1. 连接重试次数(RetryAttempts):指定在连接池无法获取到可用连接时的重试次数。可以使用setRetryAttempts()方法来设置。
lettuceConnectionFactory.setRetryAttempts(retryAttempts);
  1. 连接重试间隔时间(RetryInterval):指定连接重试的间隔时间,即每次重试之间的等待时间。可以使用setRetryInterval()方法来设置。
lettuceConnectionFactory.setRetryInterval(retryInterval);

以上是一些常用的连接池参数的配置方法。根据实际需求,您可以根据需要设置这些参数来优化连接池的性能。

4. 基本操作

1. 如何创建Lettuce连接

你可以使用RedisClientRedisClusterClientconnect()方法来建立一个连接。例如:

RedisClient redisClient = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = redisClient.connect();

2. Lettuce的基本操作如增删改查

可以使用RedisCommands的对应方法进行操作。例如:

RedisCommands<String, String> syncCommands = connection.sync();
// 添加键值对
syncCommands.set("key", "value");
// 获取键值对
String value = syncCommands.get("key");
// 删除键值对
syncCommands.del("key");
// 修改键值对
syncCommands.set("key", "newValue");

3. Lettuce的事务操作

Lettuce支持事务操作,可以使用multi()和exec()方法进行事务的开始和提交:

RedisCommands<String, String> syncCommands = connection.sync();
// 开启事务
syncCommands.multi();
syncCommands.set("key1", "value1");
syncCommands.set("key2", "value2");
// 提交事务
syncCommands.exec();

4. Lettuce的管道操作

Lettuce支持管道操作,可以使用RedisCommandsautoFlushCommands()方法来关闭自动刷新,然后用flushCommands()方法来手动刷新:

RedisCommands<String, String> syncCommands = connection.sync();
syncCommands.setAutoFlushCommands(false);
syncCommands.set("key1", "value1");
syncCommands.set("key2", "value2");
syncCommands.flushCommands();

5. Lettuce的发布订阅操作

Lettuce支持Redis的发布订阅模式,例如:

RedisCommands<String, String> syncCommands = connection.sync();
// 订阅频道
RedisPubSubCommands<String, String> pubSubCommands = connection.sync();
pubSubCommands.subscribe("channel");
// 发布消息
syncCommands.publish("channel", "message");

6. Lettuce的脚本执行

Lettuce支持Lua脚本,可以使用RedisScriptingCommandseval()evalsha()方法来执行脚本:

RedisScriptingCommands<String, String> scriptingCommands = connection.sync();
// 执行Lua脚本
String result = scriptingCommands.eval("return redis.call('get', KEYS[1])", ScriptOutputType.VALUE, new String[]{"key"});

注意:以上代码示例假设你已经有了一个有效的StatefulRedisConnection<String, String>对象。

5. 错误处理和重试

Lettuce的错误处理机制和重试策略,如何处理连接错误和命令执行失败等情况。

import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.RedisCommandExecutionException;
import io.lettuce.core.RedisConnectionException;
import io.lettuce.core.RedisCommandInterruptedException;
import io.lettuce.core.RedisCommandTimeoutException;

public class RedisExample {

    public static void main(String[] args) {
        RedisClient redisClient = RedisClient.create("redis://localhost:6379/");
        try {
            StatefulRedisConnection<String, String> connection = redisClient.connect();
            
            try {
                String result = connection.sync().get("key");
                System.out.println(result);
            } catch (RedisCommandExecutionException e) {
                System.err.println("Command execution failed: " + e.getMessage());
            } catch (RedisCommandInterruptedException e) {
                System.err.println("Command interrupted: " + e.getMessage());
            } catch (RedisCommandTimeoutException e) {
                System.err.println("Command timed out: " + e.getMessage());
            } finally {
                connection.close();
            }

        } catch (RedisConnectionException e) {
            System.err.println("Failed to connect to Redis: " + e.getMessage());
        } finally {
            redisClient.shutdown();
        }
    }
}

1. Lettuce的常见异常

  1. RedisConnectionException:当无法连接到Redis服务器时,或在尝试发送命令时连接已关闭或断开,将抛出此异常。

  2. RedisCommandTimeoutException:当命令的执行超过设定的超时时间时,将抛出此异常。

  3. RedisCommandInterruptedException:当等待命令完成的过程中线程被中断,将抛出此异常。

  4. RedisCommandExecutionException:当Redis命令执行失败时(如键不存在,类型不匹配等),将抛出此异常。

2. 如何处理这些异常

  1. RedisConnectionException:检查你的Redis服务器是否正在运行,网络连接是否畅通。如果是因为连接已关闭或断开,可以尝试重新连接。

  2. RedisCommandTimeoutException:可以尝试增加命令的超时时间,或者查看Redis服务器是否有性能问题,如CPU使用过高,磁盘IO过高等。

  3. RedisCommandInterruptedException:可以查看线程为何被中断,并尝试解决中断的原因。

  4. RedisCommandExecutionException:检查你的Redis命令是否正确,如键是否存在,类型是否匹配等。如果命令没有问题,则可能是Redis服务器的问题,需要检查服务器的状况。

6. Lettuce vs Jedis

维度/库LettuceJedis
单线程/多线程Lettuce是基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,应该被用作长期存在的线程安全对象。Jedis实例不是线程安全的,因此在多线程环境下,你需要每个线程创建一个新的连接实例,或者使用连接池。
阻塞/非阻塞Lettuce支持异步、反应式、同步和非阻塞操作。Jedis操作是同步阻塞的,不支持异步和非阻塞操作。
集群支持Lettuce提供了Redis Cluster的原生支持。Jedis也支持Redis Cluster,但需要手动处理重定向。
PUB/SUB模型Lettuce支持发布-订阅模型。Jedis也支持发布-订阅模型。
二进制协议Lettuce直接使用Netty来处理命令和结果,可以处理任何Redis协议和命令。Jedis使用自己的协议处理器,对协议的支持可能不太完整。
项目活跃度Lettuce是目前最活跃的Redis Java客户端项目,一直在持续更新和添加新特性。Jedis的活跃度较低,更新和新功能的添加较慢。
连接池Lettuce的连接实例是线程安全的,大多数情况下,你不需要使用连接池。不过,Lettuce也提供了一个可选的内置连接池。在多线程环境下,你需要使用Jedis的连接池来管理和复用连接。
依赖Lettuce依赖于Netty。Jedis没有外部依赖。
事务Lettuce支持Redis的事务。Jedis也支持Redis的事务。
SentinelLettuce提供了对Redis Sentinel的原生支持。Jedis也支持Redis Sentinel。

7. 参考资料

Lettuce

  1. 官方文档:Lettuce
  2. GitHub:Lettuce GitHub
  3. 深入了解Lettuce:Understanding Lettuce
  4. Lettuce源码分析:Lettuce source code analysis

Jedis

  1. 官方文档:Jedis
  2. GitHub:Jedis GitHub
  3. 深入了解Jedis:Understanding Jedis
  4. Jedis源码分析:Jedis source code analysis

Redis

  1. 官方文档:Redis
  2. GitHub:Redis GitHub
  3. Redis命令:Redis commands
  4. Redis入门教程:Redis tutorial

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

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

相关文章

Halcon (2):Halcon基础知识

文章目录 文章专栏视频资源前言Halcon文档案例学习结论 文章专栏 Halcon开发 视频资源 机器视觉之C#联合Halcon 前言 本章我们主要讲解Halcon的基础语法 Halcon文档 按下F1&#xff0c;就可以看到Halcon的文档&#xff0c;不过都是纯英文的 如果不清楚参数如何使用&#x…

十三、Docker的安装

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

异地工业设备集中运维、数据采集,一招搞定

为了提升运维效率&#xff0c;能够及时发现和响应设备的故障、异常和潜在问题。 越来越多的企业都在搭建“集中式”的远程智慧运维体系&#xff0c;以提高运维效率和降低成本。 异地工业设备远程运维&#xff0c;提升响应效率、降低运维成本 以国内陕西某机床公司为例&#xff…

Buildroot 添加 Qt 支持

Buildroot 添加 Qt 支持 lqonlylove 于 2022-12-03 13:37:34 发布 阅读量2.8k 收藏 12 点赞数3 分类专栏: 根文件系统制作 文章标签: qt buildroot 版权 ​编辑根文件系统制作专栏收录该内容 2 篇文章0 订阅 订阅专栏 一、制作根文件系统 Buildroot 制作根文件系统_l…

【IT杂谈】--数据中台和BI项目失败的原因分析--以M集团传统制造业为例

“我们这个BI怎么做成这副鸟样&#xff0c;他们还想要钱&#xff0c;我们的尾款是不可能付的。”这是我在G集团听到财务总监的抱怨。感觉类似于这种吐槽BI的话&#xff0c;我经常能够听到的。我正在经历第四家公司&#xff0c;有三家公司都上了BI分析平台&#xff0c;但是效果都…

plantuml最原始的主题如何设置

在startuml下一行添加 skin rose startuml skin rose:Hello world; :This is defined on several **lines**;enduml 效果如下&#xff1a; plantuml官网地址如下&#xff1a; ​​​​​​使用简单的文字描述画UML图的开源工具。轻松从简单的文字说明创建UML图。也有许多种可…

信号的机制——信号的发送与处理

对于硬件触发的&#xff0c;无论是中断&#xff0c;还是信号&#xff0c;肯定是先到内核的&#xff0c;然后内核对于中断和信号处理方式不同。一个是完全在内核里面处理完毕&#xff0c;一个是将信号放在对应的进程 task_struct 里信号相关的数据结构里面&#xff0c;然后等待进…

Leetcode—剑指Offer LCR 140.训练计划II【简单】

2023每日刷题&#xff08;三十三&#xff09; Leetcode—LCR 140.训练计划II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* trainingPlan(struct ListNode* head, int cnt) {str…

【好奇心驱动力】ESP8266驱动SG90舵机开关灯

0.前言 ESP8266弄丢了好几个都忘记放在哪&#xff0c;重新买了个typeC接口的方便多了&#xff0c;看到驱动SG90舵机作为智能开关&#xff0c;简单复现了一下&#xff0c;代码比较简单&#xff0c;没有连接小爱同学或者其他语音助手。 1.实验方法 ESP8266连接SG90舵机&#x…

Java中的集合内容总结——Collection接口

集合概述 Java 集合可分为 Collection 和 Map 两大体系&#xff1a; Collection接口&#xff1a;用于存储一个一个的数据。 List子接口&#xff1a;用来存储有序的、可以重复的数据&#xff08;主要用来替换数组&#xff0c;"动态"数组&#xff09; 实现类&#xf…

gRPC 的原理 介绍带你从头了解gRPC

gRPC 的原理 什么是gRPC gRPC的官方介绍是&#xff1a;gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架&#xff0c;基于 HTTP2 协议设计&#xff0c;序列化使用PB(Protocol Buffer)&#xff0c;PB 是一种语言无关的高性能序列化框架&#xff0c;基于 HTTP2PB 保…

一起Talk Android吧(第五百五十三回:解析Retrofit返回的数据)

文章目录 1. 知识回顾2. 解析方法2.1 解析有效数据2.2 解析错误数据3. 示例代码4. 经验与总结4.1 经验分享4.2 内容总结各位看官们大家好,上一回中咱们说的例子是"Retrofit的基本用法",本章回中介绍的例子是" 如何解析Retrofit返回的数据"。闲话休提,言…

解决Redis分布式锁宕机出现不可靠问题-zookeeper分布式锁

核心思想&#xff1a;当客户端要获取锁&#xff0c;则创建节点&#xff0c;使用完锁&#xff0c;则删除该节点。 客户端获取锁时&#xff0c;在 lock 节点下创建临时顺序节点。然后获取 lock下面的所有子节点&#xff0c;客户端获取到所有的子节点之后&#xff0c;如果发现自己…

hcia学习:

视频学习&#xff1a; 第一部分&#xff1a;基础学习。 19——子网掩码。 27——防火墙配置&#xff1a; 32——企业级路由器配置&#xff1a; 基础实验完成&#xff1a;&#xff08;完成以下目录对应的实验&#xff0c;第一部分基础实验就完成。&#xff09; 方法&#xff…

高校教师资格证备考

高等教育制度 关于人的全面发展和个体发展的关系&#xff0c;说法正确的是&#xff08;ABC&#xff09;。 A.个体发展是在全面发展基础上的选择性发展 B.全面发展是个体发展的前提和基础 C.个体发展又是全面发展的动力 D.个体发展是全面发展的前提和基础

Vue3-自定义hook函数

Vue3-自定义hook函数 功能&#xff1a;可以将组合式API封装成一个函数&#xff0c;用于解决代码复用的问题。注意&#xff1a;需要在src文件夹下创建一个文件夹hooks&#xff0c;在里面放js文件&#xff0c;命名随意&#xff0c;主要是将setup函数中的代码放入js文件中。 // s…

C++加持让python程序插上翅膀——利用pybind11进行c++和python联合编程示例

目录 0、前言1、安装 pybind11库c侧python侧 2、C引入bybind11vs增加相关依赖及设置cpp中添加头文件及导出模块cpp中添加numpy相关数据结构的接收和返回编译生成dll后改成导出模块同名文件的.pyd 3、python调用c4、C引入bybind11 0、前言 在当今的计算机视觉和机器学习领域&am…

x程无忧sign逆向分析

x程无忧sign逆向分析&#xff1a; 详情页sign&#xff1a; 详情页网站&#xff1a; import base64 # 解码 result base64.b64decode(aHR0cHM6Ly9qb2JzLjUxam9iLmNvbS9ndWFuZ3pob3UvMTUxODU1MTYyLmh0bWw/cz1zb3Vfc291X3NvdWxiJnQ9MF8wJnJlcT0zODQ4NGQxMzc2Zjc4MDY2M2Y1MGY2Y…

十. Linux关机重启命令与Vim编辑的使用

关机重启命令 shutdown命令 其他关机命令 其他重启命令 系统运行级别 系统默认运行级别与查询 退出登录命令logout 文本编辑器Vim Vim简介 没有菜单,只有命令Vim工作模式 Vim常用命令 插入命令 定位命令 删除命令 复制和剪切命令 替换和取消命令 搜索和搜索替换命令 保存和退出…

为什么Transformer模型中使用Layer Normalization(Layer Norm)而不是Batch Normalization(BN)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…