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

Redis 常见面试题汇总(持续更新)

文章目录

    • 01、Redis 支持哪些数据类型?
    • 02、谈谈对 Redis 的 AOF 机制的 rewrite 模式的理解?
    • 03、请列举几个 Redis 常见性能问题和解决方案
    • 04、Redis 使用的最大内存是多少?内存数据淘汰策略有哪些?
    • 05、请谈谈 Redis 的同步机制。
    • 06、谈谈对 Redis 哈希槽的理解。
    • 07、什么是缓存雪崩?
    • 08、什么是缓存击穿?
    • 09、什么是缓存预热?
    • 10、如何进行缓存更新?
    • 11、如何进行缓存降级?
    • 12、如何缓存热点 Key?
    • 13、什么是NoSQL数据库?
    • 14、NoSQL和RDBMS有什么区别?
    • 15、在哪些情况下使用和不使用NoSQL数据库?
    • 14、非关系型数据库有哪些?

01、Redis 支持哪些数据类型?

答:Redis 支持五种基本数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)及 ZSet(Sorted Set 有序集合)。还支持 HyperLogLog、Geo、BitMap、Pub/Sub 等数据结构,此外还有 BloomFilter,RedisSearch、Redis - ML 等。

  • HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。HyperLogLog 只会根据输入元素来计算基数,而不会存储输入元素本身。
  • Geo 用于地理位置的存储和计算,Redis3.2 版本开始提供此功能。
  • BitMap 实际上不是特殊的存储结构,其本质上是二进制字符串,可以进行位操作,其经典应用场景之一是日活跃用户统计。

02、谈谈对 Redis 的 AOF 机制的 rewrite 模式的理解?

答:rewrite 模式的作用就是缩小 AOF 持久化文件的体积。由于 AOF 持久化会对每一个写操作进行日志记录,在访问量时大时文件体积会迅速膨胀,这就需要通过 rewrite 模式来缩小文件体积。

rewrite 会像 replication 一样,创建(fork)出一个子进程,以及创建一个临时文件,遍历当前内存数据库中的所有数据,输出到临时文件。在 rewrite 期间的写操作会保存在内存的 rewrite buffer 中,当 rewrite 成功后这些操作也会复制到临时文件中,在最后用临时文件替代 AOF 文件。

触发 rewrite ,是文件大小达到临界点时发生。这个临界点是在 Redis 配置文件 Redis.conf 中配置,相关有两个参数:auto - aof - rewrite - percentageauto - aof - rewrite - min - size 参数。当前 AOF 文件体积大于 auto - aof - rewrite - min - size ,同时 AOF 文件体积的增长率大于 auto - aof - rewrite - percentage 时,会自动触发 AOF 的 rewrite 模式。当然也可手动调用 startAppendOnly 函数来触发 rewrite

以上情况在 AOF 打开的情况下发生,如果 AOF 是关闭的,那么 rewrite 操作可以通过 bgrewriteaof 命令来进行。

03、请列举几个 Redis 常见性能问题和解决方案

答:这里列举几个常见的性能问题如下:

  • 1)Master 最好不要做 RDB 持久化,因为这时 save 命令会调度 rdbsSave 函数,会阻塞主线程的工作,当数据量比较大时可能造成主线程长时间间断性暂停服务。
  • 2)如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒一次。
  • 3)为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网中。
  • 4)尽量避免在运行压力很大的主库上增加从库。
  • 5)主从复制不要用图状结构,用单向链表结构更为稳定,即:Master→Slave1→Slave2→Slave3… 。这样的结构方便解决单点故障问题,实现 Slave 对 Master 的替换。如果 Master 崩溃,可以立即启用 Slave1 替换 Master,其他不变。

04、Redis 使用的最大内存是多少?内存数据淘汰策略有哪些?

答:在 Redis 中,最大使用内存大小由 Redis.conf 中的参数 maxmemory 决定。默认值为 0,表示不限制,这时实际相当于当前系统的内存。但如果随着数据的增加,如果对内存中的数据没有管理机制,那么数据集大小达到或超过最大内存的大小时,则会造成 Redis 崩溃。因此需要内存数据淘汰机制。

Redis 淘汰策略配置参数为 maxmemory - policy,默认为 volatile - lru,Redis 总共提供了 6 种数据淘汰策略。

  • 1)volatile - lru:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
  • 2)volatile - ttl:从已设置过期时间的数据集中挑选最近使用的数据集淘汰。
  • 3)volatile - random:从已设置过期时间的数据集中任意选择数据淘汰。
  • 4)allKeys - lru:从数据集中挑选最近最少使用的数据淘汰。
  • 5)allKeys - random:从数据集中任意选择数据淘汰。
  • 6)no - eviction(驱逐):禁止驱逐数据,这是默认的策略。

如果 AOF 已开启,Redis 淘汰数据时也会同步到 AOF。
说明一下:volatile 开头表示是对已设置过期时间的数据集淘汰数据,allKeys 开头表示是从全部数据集淘汰数据,后面的 lru、ttl、random 表示的是不同的淘汰策略,no - eviction 是永不回收的数据集合。关于 lru 策略,需要说明的是,Redis 中并不会准确的删除所有键中最近最少使用的键,而是随机抽取 5 个键(个数由参数 maxmemory - samples 决定,默认值是 5),删除这 5 个键中最近最少使用的键。

这里也介绍一下使用淘汰策略的规则:

  • 如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用 allKeys - lru
  • 如果数据呈现等分布,也就是所有的数据访问频率大体相同,则使用 allKeys - random

05、请谈谈 Redis 的同步机制。

答:Redis 的主从同步分为部分同步(也叫增量同步)和全量同步。Redis 会先尝试进行增量同步,如不成功,则 Slave 进行全量同步。如果有需要,Slave 在任何时候都可以发起全量同步。

Redis 增量同步是指 Slave 初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。增量同步的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

Redis 全量同步一般发生在 Slave 初始化阶段,这时 Slave 需要对 Master 上的所有数据做全量同步。全同步结束后,也就是配置好主从后,Slave 连接到 Master,Slave 都会发送 PSYNC(即增量同步)命令到 Master。

如果是重新连接,且满足增量同步的条件,那么 Redis 会将内存缓存队列中的命令发给 Slave,完成增量同步。否则进行全量同步。

06、谈谈对 Redis 哈希槽的理解。

答:Redis Cluster 提供了自动将数据分散到不同结点的能力,但采取的策略不是一致性 hash,而是哈希槽。Redis 集群将整个 key 的数值域分成 16384 个哈希槽,每个 Key 通过 CRC16 校验后对 16384 取模来决定放置到哪个槽,集群的每个结点负责一部分哈希槽。

文章:Redis 的缓存雪崩、缓存穿透和缓存击穿详解,并提供多种解决方案,该文章对这三个问题作了详细解释。

07、什么是缓存雪崩?

答:如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,这就造成了缓存雪崩。
下面推荐几个缓存雪崩的解决办法:

  • 1)在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 Key 只允许一个线程查询数据和写缓存,其他线程等待。
  • 2)可以通过缓存 reload 机制,预先去更新缓存,亦即将发生高并发访问前手动触发加载缓存。
  • 3)对不同的 Key,设置不同的过期时间,让缓存失效的时间点尽量均匀。比如我们可以在原有的失效时间基础上增加一个随机值,比如 1 - 5 分钟随机。这样每一个缓存的过期时间的重复率就会大大降低缓存集体失效的概率。
  • 4)设置二级缓存,或者双缓存策略。A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2 缓存失效时间设置为短期,A2 设置为长期。

08、什么是缓存击穿?

答:缓存击穿,是指一个 Key 在不停地支撑着高并发,高并发集中对这一个点进行访问,当这个 Key 在失效的瞬间,持续的高并发就穿破缓存,直接请求数据库。缓存击穿和缓存雪崩的区别在于缓存击穿是针对某一个 Key 缓存而言,缓存雪崩则是针对很多 Key。

对一般的网站而言,很难有某个数据能达到缓存击穿的级别,一般是热门网站的秒杀或爆款商品,才有可能发生这种情况。当然,这时把这种商品设置成永不过期或者过期时间超过抢购时段是一种很好的避免发生缓存击穿的方法,如果这时可以不需要考虑数据一致性的问题的话。

09、什么是缓存预热?

答:缓存预热就是系统上线时,提前将相关的缓存数据直接加载到缓存系统,而不是等到用户请求的时候,才将查询数据缓存。这样用户请求可直接查询事先被预热的缓存数据。缓存预热的方式可以有如下几种:

  • 1)直接写个缓存刷新页面,上线时手工操作。
  • 2)数据量不大,可以在项目启动的时候自动进行加载。
  • 3)定时刷新缓存。

10、如何进行缓存更新?

答:我们知道在缓存中通过 expire 来设置 Key 的过期时间,各缓存服务器一般都有自带的缓存失效策略,这里讲的缓存更新,是指源数据更新之后如何解决缓存数据一致性的问题。个人认为有如下方案:

  • 1)数据实时同步失效或更新。这是一种增量主动型的方案,能保证数据强一致性,在数据库更新之后,主动请求缓存更新。
  • 2)数据异步更新,这是属于增量被动型方案,数据一致性稍弱,数据更新会有所延迟。一般在数据库后,通过异步方式,用多线程方式或消息队列来实现更新。
  • 3)定时任务更新,这是一种全量被动型方案,当然也可以是增量被动型。这种方式保证数据最终一致性,通过定时任务按一定频率调度更新缓存数据一致性最差。

具体采用何种方式,开发者可以根据实际需要来进行取舍。

11、如何进行缓存降级?

答:在网上看到很多地方提到缓存降级,但笔者的理解,很多文章所说的缓存降级,其实都应该是指服务降级。就是说在访问量剧增、服务响应出现问题(如响应延迟或不响应)或非核心服务影响到核心流程的性能的情况下,仍然需要保证核心服务可用,尽管可能一些非主要服务不可用,这时就可以采取服务降级策略。

服务降级的最终目的是保证核心服务可用,即使是有损的。服务降级应当事先确定好降级方案,确定哪些服务是可以降级的,哪些服务是不可降级的。根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心服务的正常运行。

降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。

  • 根据服务方式:可以拒接服务,可以延迟服务,也可以随机提供服务。
  • 根据服务范围:可以暂时禁用某些功能或禁用某些功能模块。

总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。

12、如何缓存热点 Key?

答:使用缓存 + 过期时间的策略既可以提高数据读取速度,又能保证数据的定期更新,这种模式基本能够满足绝大部分需求。但是如果当前Key是一个热点Key,并发量非常大,这时就可能产生前面所说的缓存击穿问题。

重建缓存可能是个复杂操作,可能包含有复杂计算 (例如复杂的SQL、多次I/O、多个依赖等)。如果在缓存失效的瞬间,有大量请求进行并发访问,这些访问都会同时访问后端(也就会同时进行重建缓存操作),就会造成后端负载加大,甚至可能造成应用崩溃。

所以缓存热点 Key 为了避免缓存击穿,一是可以设置为永不过期,在不需要考虑数据一致性问题的情况下,个人认为这是最好也最简单的解决方式。如果需要考虑数据一致性问题,需要设置过期时间,那就要考虑如何减少重建缓存的次数,这时采用Redis 的互斥锁是一种解决方式, 这样保证同一时间只能有一个请求执行缓存重建。这样就能有效减少缓存重建次数,但如果重建时间过长,则可能引发其他问题。

13、什么是NoSQL数据库?

答: NoSQL是非关系型数据库的意思,也有的解释成Not Only SQL。

  • 非关系型数据库是对不同于传统关系型数据库的统称。
  • 非关系型数据库的显著特点是不使用SQL作为查询语言,数据存储不需要特定的表格模式。
  • 由于简单的设计和非常好的性能所以被用于大数据和手机App等。

NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。

14、NoSQL和RDBMS有什么区别?

关系型数据库采用的结构化的数据,NoSQL采用的是键值对的方式存储数据。

15、在哪些情况下使用和不使用NoSQL数据库?

在处理非结构化/半结构化的大数据时,在水平方向上进行扩展时,随时应对动态增加的数据项时可以优先考虑使用NoSQL数据库。

在考虑数据库的成熟度、支持、 分析和商业智能、管理及专业性等问题时,应优先考虑关系型数据库。

14、非关系型数据库有哪些?

  • Membase:开源项目,NoSQL 家族新的重量级的成员。
  • Mongodb:一个基于分布式文件存储的数据库。
  • Hypertable:是一个开源、高性能、可伸缩的数据库,它采用与 Google 的 Bigtable 相似的模型。
  • HBase:一个分布式的、面向列的开源数据库。
  • Neo4j:一个高性能的 NoSQL 图形数据库,它将结构化数据存储在网络上而不是表中。
  • Redis:基于内存亦可持久化的日志型、Key - Value 型数据库。

相关文章:

Redis 常见面试题汇总(持续更新)

文章目录 01、Redis 支持哪些数据类型?02、谈谈对 Redis 的 AOF 机制的 rewrite 模式的理解?03、请列举几个 Redis 常见性能问题和解决方案04、Redis 使用的最大内存是多少?内存数据淘汰策略有哪些?05、请谈谈 Redis 的同步机制。…...

蓝桥杯备赛 Day13.1走出迷宫

链接:走出迷宫 题目描述 小明现在在玩一个游戏,游戏来到了教学关卡,迷宫是一个N*M的矩阵。 小明的起点在地图中用“S”来表示,终点用“E”来表示,障碍物用“#”来表示,空地用“.”来表示。 障碍物不能通…...

全面解析鸿蒙(HarmonyOS)开发:从入门到实战,构建万物互联新时代

文章目录 引言 一、鸿蒙操作系统概述二、鸿蒙开发环境搭建三、鸿蒙核心开发技术1. **ArkUI框架**2. **分布式能力开发**3. **原子化服务与元服务** 四、实战案例:构建分布式音乐播放器五、鸿蒙开发工具与调试技巧六、鸿蒙生态与未来展望结语 引言 随着万物互联时代…...

使用 mkcert 本地部署启动了 TLS/SSL 加密通讯的 MongoDB 副本集和分片集群

MongoDB 是支持客户端与 MongoDB 服务器之间启用 TLS/SSL 进行加密通讯的, 对于 MongoDB 副本集和分片集群内部的通讯, 也可以开启 TLS/SSL 认证. 本文会使用 mkcert 创建 TLS/SSL 证书, 基于创建的证书, 介绍 MongoDB 副本集、分片集群中启动 TLS/SSL 通讯的方法. 我们将会在…...

P3372 【模板】线段树 1【题解2】

本题题解分两篇 此篇为第贰篇,用树状数组做 第壹篇:P3372 【模板】线段树 1【题解1】 本文讲解树状数组解决区间修改区间查询 其它树状数组相关文章: 树状数组讲解单点修改/查询树状数组解决区间修改单点查询 P3372 【模板】线段树 1 题…...

使用 EDOT 监测由 OpenAI 提供支持的 Python、Node.js 和 Java 应用程序

作者:来自 Elastic Adrian Cole Elastic 很自豪地在我们的 Python、Node.js 和 Java EDOT SDK 中引入了 OpenAI 支持。它们为使用 OpenAI 兼容服务的应用程序添加日志、指标和跟踪,而无需任何代码更改。 介绍 去年,我们宣布了 OpenTelemetry…...

kotlin中expect和actual关键字修饰的函数作用

在 Kotlin 多平台编程中,expect 和 actual 关键字用于定义跨平台的抽象和具体实现。这种机制允许开发者声明一个平台无关的接口或函数签名(使用 expect),然后在每个目标平台上提供具体的实现(使用 actual)。…...

CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测,光伏功率预测

CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测,光伏功率预测 代码下载:CNN-BiGRU卷积神经网络双向门控循环单元多变量多步预测,光伏功率预测 一、引言 1.1、研究背景及意义 随着全球能源危机和环境问题的日益严重,可再…...

mysql8.0使用MGR实现高可用与利用MySQL Router构建读写分离MGR集群

MGR是MySQL Group Replication的缩写,即MySQL组复制。 在以往,我们一般是利用MySQL的主从复制或半同步复制来提供高可用解决方案,但这存在以下几个比较严重的问题: 主从复制间容易发生复制延迟,尤其是在5.6以前的版本…...

保研考研机试攻略:python笔记(4)

🐨🐨🐨15各类查找 🐼🐼二分法 在我们写程序之前,我们要定义好边界,主要是考虑区间边界的闭开问题。 🐶1、左闭右闭 # 左闭右闭 def search(li, target): h = len(li) - 1l = 0#因为都是闭区间,h和l都可以取到并且相等while h >= l:mid = l + (h - l) // 2…...

如何保证缓存和数据库一致性

保证缓存和数据库一致性是分布式系统中的一个常见挑战。以下是几种常用的策略和方法,用于解决缓存与数据库之间的数据一致性问题: 1. 基础同步策略 基础同步策略包括以下几种常见的操作顺序: 先更新缓存再更新数据库:这种方法可能导致缓存中的数据成为脏数据,因为如果数…...

关于conda换镜像源,pip换源

目录 1. 查看当前下载源2. 添加镜像源2.1清华大学开源软件镜像站2.2上海交通大学开源镜像站2.3中国科学技术大学 3.删除镜像源4.删除所有镜像源,恢复默认5.什么是conda-forge6.pip换源 1. 查看当前下载源 conda config --show channels 如果发现多个 可以只保留1个…...

分布式服务框架 如何设计一个更合理的协议

1、概述 前面我们聊了如何设计一款分布式服务框架的问题,并且编码实现了一个简单的分布式服务框架 cheese, 目前 cheese 基本具备分布式服务框架的基本功能。后面我们又引入了缓存机制,以及使用Socket替代了最开始的 RestTemplate。并且还学习了网络相关…...

git客户端版本下载

1. 访问官方网站:您可以在git官方网站(https://git-scm.com)上找到git软件最新稳定版下载链接。 2.如果需要下载其它版本,可访https://github.com/git-for-windows/git/releases选择想要的版本下载。...

前端快速生成接口方法

大家好,我是苏麟,今天聊一下OpenApi。 官网 : umijs/openapi - npm 安装命令 npm i --save-dev umijs/openapi 在根目录(项目目录下)创建文件 openapi.config.js import { generateService } from umijs/openapi// 自…...

mysql 学习12 存储引擎,mysql体系结构

mysql 体系结构 存储引擎简介 存储引擎 就是 存储数据,建立索引,更新/查询 数据等技术的实现方式。 存储引擎 是基于表的,而不是基于库的,所以存储引擎也可以称为 表类型 mysql默认的使用InnoDB 做为存储引擎 查看一下我们之前…...

【Java八股文】02-Java集合面试篇

【Java八股文】02-Java集合面试篇 概念数组与集合区别常用集合Java中的线程安全的集合是什么?Collections和Collection的区别 Listjava中list的几种实现把ArrayList变成线程安全的有哪些方法?CopyOnWriteArrayList是如何保证线程安全的? Mapj…...

稀土抑烟剂——为汽车火灾安全增添防线

一、稀土抑烟剂的基本概念 稀土抑烟剂是一类基于稀土元素(如稀土氧化物和稀土金属化合物)开发的高效阻燃材料。它可以显著提高汽车内饰材料的阻燃性能,减少火灾发生时有毒气体和烟雾的产生。稀土抑烟剂不仅能提升火灾时的安全性,…...

Unity进阶教程AOI算法原理详解

最新课程《全栈双客户端(Unity/Cocos) TurnKey方案》更新了AOI专题,今天分享一下AOI算法的实现原理。 AOI的功能和作用 在MMORPG网路游戏当中,单服同时在线一般都会有几千人。当有个玩家执行一个操作,理想情况下要把玩家的操作广播同步给单…...

Python中的HTTP客户端库:httpx与request | python小知识

Python中的HTTP客户端库:httpx与request | python小知识 在Python中,发送HTTP请求和处理响应是网络编程的基础。requests和httpx是两个常用的HTTP库,它们都提供了简洁易用的API来发送HTTP请求。然而,httpx作为新一代的HTTP客户端…...

ASP.NET Core SignalR的分布式部署

假设聊天室程序被部署在两台服务器上,客户端1、2连接到了服务器A上的ChatRoomHub,客户端3、4连接到服务器B上的ChatRoomHub,那么客户端1发送群聊消息时,只有客户端1、2能够收到,客户端3、4收不到;在客户端3…...

【Elasticsearch】match查询

Elasticsearch 的match查询是全文搜索中最常用和最强大的查询类型之一。它允许用户在指定字段中搜索文本、数字、日期或布尔值,并提供了丰富的功能来控制搜索行为和结果。以下是match查询的详细解析,包括其工作原理、参数配置和使用场景。 1.match查询的…...

AndroidStudio中可用的Ai插件

GitHub Copilot 这是我目前主用的,还行 1. 安装 打开 Android Studio:启动您的 Android Studio。 导航到插件设置: 点击菜单栏中的 File(文件) > Settings(设置)。在设置窗口中&#xff0…...

【C】链表算法题7 -- 环形链表||

leetcode链接https://leetcode.cn/problems/linked-list-cycle-ii/description/ 问题描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到…...

STM32系统架构介绍

STM32系统架构 1. CM3/4系统架构2. CM3/4系统架构-----存储器组织结构2.1 寄存器地址映射(特殊的存储器)2.2 寄存器地址计算2.3 寄存器的封装 3. CM3/4系统架构-----时钟系统 STM32 和 ARM 以及 ARM7是什么关系? ARM 是一个做芯片标准的公司&#xff0c…...

Android Studio:EditText常见4种监听方式

1. 文本变化监听(TextWatcher) TextWatcher 主要用于监听 EditText 里的文本变化,它有三个方法: beforeTextChanged(文本变化前)onTextChanged(文本正在变化时)afterTextChanged&a…...

window patch按块分割矩阵

文章目录 1. excel 示意2. pytorch代码3. window mhsa 1. excel 示意 将一个三维矩阵按照window的大小进行拆分成多块2x2窗口矩阵,具体如下图所示 2. pytorch代码 pytorch源码 import torch import torch.nn as nn import torch.nn.functional as Ftorch.set_p…...

机器学习(李宏毅)——BERT

一、前言 本文章作为学习2023年《李宏毅机器学习课程》的笔记,感谢台湾大学李宏毅教授的课程,respect!!! 读这篇文章必须先了解self-attention、Transformer,可参阅我其他文章。 二、大纲 BERT简介self-…...

数据科学之数据管理|统计学

使用python学习统计 目录 01 统计学基础 7 一、 统计学介绍 7 二、 数据和变量 8 02 描述统计 10 一、 描述统计概述 10 二、 分类变量的描述 11 三、 等距数值变量的描述 13 四、 等比数值变量的描述 16 五、 常用软件包介绍 16 六、 数值变量的描述统计 18 (一)…...

深度学习-111-大语言模型LLM之基于langchain的结构化输出功能实现文本分类

文章目录 1 langchain的结构化输出1.1 推荐的使用流程1.2 模式定义1.3 返回结构化输出1.3.1 工具调用(方式一)1.3.2 JSON模式(方式二)1.3.3 结构化输出法(方式三)2 文本分类2.1 定义分类模式2.2 配置分类提示模板2.3 初始化分类模型2.4 分类示例3 参考附录1 langchain的结构化输…...