自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(104)
  • 收藏
  • 关注

原创 Paimon Branch

Paimon的分支功能通过文件系统隔离实现数据版本控制,支持从主分支(main)创建独立分支进行实验性操作,不影响主干数据。每个分支拥有独立的快照和Schema演进历史,底层通过BranchManager接口(含createBranch、dropBranch等方法)和FileSystemBranchManager实现元数据隔离。系统表BranchesTable动态展示分支信息,而scan.fallback-branch特性允许主分支缺失分区时自动回退到指定分支查询。该设计兼顾代码复用与数据隔离

2025-07-16 21:37:26 454

原创 Kafka 时间轮深度解析:如何O(1)处理定时任务

Kafka的时间轮(TimingWheel)是一种高效管理大量定时任务的算法结构,相比传统优先队列(O(logn))具有近乎O(1)的添加/删除性能。其核心设计包括:分层时间轮通过多级轮盘(底层tickMs=1ms,上层tickMs逐级放大)支持任意长延时任务;DelayQueue驱动机制实现无空转的任务到期检测;TimerTaskList采用双向循环链表组织同周期任务。系统通过SystemTimerReaper线程自动推进时钟,结合读写锁保证线程安全。该结构在Kafka中广泛应用于请求超时管理

2025-07-16 09:58:09 384

原创 Paimon 删除向量

RowKind和DeletionVector是Paimon中两种不同的数据删除机制。RowKind作用于逻辑层,通过标记变更类型(增删改)配合主键表的LSM-Tree结构实现数据合并,但仅适用于主键表且存在读取开销。DeletionVector则采用物理层的位图标记方式,通过独立索引文件记录删除行位置,实现读时过滤,具有通用性高、I/O开销小的优势,适用于所有表类型。二者各有侧重,DeletionVector通过轻量级标记机制显著提升了删除操作的性能和适用范围,是Paimon实现高效数据更新的关键技术。

2025-07-15 22:06:12 424

原创 TimSort 类:论Arrays.sort的稳定性

TimSort是一种混合稳定排序算法,结合归并排序和二分插入排序的优点,核心流程包括:识别自然有序子序列(run)、扩展短run至最小长度、通过归并合并run。算法通过显式栈管理run(替代递归栈),利用mergeCollapse策略保持栈平衡,优化合并效率。关键优化包括: Galloping模式:通过gallopLeft/gallopRight快速定位插入点,减少冗余比较;自适应合并:短run优先,最小化临时空间;小数组使用插入排序sort中基础对象使用双枢轴快排,其它使用TimSort

2025-07-15 18:20:27 940

原创 深入解析Paimon的RowKind数据变更机制 和 KeyValue存储

Paimon数据模型的核心组件包括RowKind和KeyValue,用于高效处理数据变更和存储。RowKind枚举定义了四种变更类型(INSERT、DELETE、UPDATE_BEFORE、UPDATE_AFTER),支持数据湖的增量更新和流式处理。KeyValue作为基本数据单元,包含主键、序列号、操作类型和业务数据,采用二进制格式实现高效序列化。BinaryRow通过紧凑的内存布局(定长和变长部分)优化数据处理性能。这些设计共同构成了Paimon高性能数据湖存储的基础,支持批流一体处理

2025-07-14 16:20:36 894

原创 Paimon核心:FileStoreWrite解析(分桶处理)

本文系统分析了Paimon中文件存储写入的核心抽象类AbstractFileStoreWrite及其子类实现。AbstractFileStoreWrite定义了通用写入框架,管理分区/分桶的RecordWriter实例,负责数据分发、合并触发及提交准备。其内存管理由MemoryFileStoreWrite扩展,通过共享内存池实现写入器间的资源均衡。仅追加表写入则通过AppendOnlyFileStoreWrite处理,支持小文件合并与内存控制。支持无桶、固定桶和动态桶,动态桶由高层负责。

2025-07-13 16:14:48 532

原创 Paimon数据写入与统计信息收集机制详解

StatsCollectingSingleFileWriter是Apache Paimon中负责收集数据文件列统计信息的核心抽象类。它继承自SingleFileWriter,在写入单个文件的同时收集字段统计信息(如最大值、最小值和空值数量)。该设计采用策略模式,通过SimpleStatsProducer接口实现统计信息生成与文件写入的解耦,支持两种策略:逐条记录收集和文件末端提取。具体子类如RowDataFileWriter和KeyValueDataFileWriter实现特定写入行为,并将统计信息封装

2025-07-13 13:35:01 916

原创 Paimon Lookup 哈希文件和Sort文件选择

Paimon的Lookup结构分为HashLookupStore和SortLookupStore两种实现。HashLookupStore通过哈希映射实现理论O(1)查找性能,但存在哈希冲突风险,构建复杂且资源占用高;SortLookupStore采用二分查找实现稳定O(logn)性能,构建效率高,资源利用率好。Paimon默认选择Sort实现,因其通用性强、性能稳定。Hash实现仅适用于对查找延迟有极致要求且能接受更高资源消耗的特定场景。两种实现各有优劣,需根据具体业务需求选择。

2025-07-12 15:53:38 693

原创 Paimon哈希lookup文件构建解析

HashLookupStoreWriter是Paimon中用于创建本地哈希查找文件的实现类,采用两阶段写入策略构建基于哈希的持久化存储结构。首先按Key长度分组收集数据到临时文件,然后在close阶段构建哈希索引并合并为最终文件。该类使用开放地址法解决哈希冲突,支持布隆过滤器和数据压缩。 配套的HashLookupStoreReader通过元数据驱动的随机访问实现高效查找,利用FileBasedRandomInputView提供直接定位能力,配合布隆过滤器快速排除不存在的Key。因为是随机访问,使用页缓存。

2025-07-12 15:07:28 918

原创 Paimon 读磁盘内存缓存设计

Paimon的缓存系统采用分层设计,核心组件包括:CacheManager:管理堆内内存缓存,分为indexCache和dataCache两个独立缓存池,分别处理索引页和数据页BlockCache:文件级缓存代理,连接CacheManager与具体文件,实现块级缓存和压缩处理MemorySlice/BlockEntry:高效内存视图组件,支持零拷贝数据访问FileBasedBloomFilter:带缓存的布隆过滤器实现,优化文件过滤性能

2025-07-11 19:33:57 769

原创 Paimon 写入磁盘文件名字生成机制

Paimon通过分层设计实现文件路径的自动生成:1) 基础目录由表根路径+分区键值+桶号拼接而成;2) DataFilePathFactory负责生成文件名,采用"前缀-UUID.格式后缀"的命名规则(如changelog-a9f8b8e8.parquet),确保唯一性;3) KeyValueFileWriterFactory为每个(分区,桶)组合创建专属实例,通过控制反转设计将路径生成逻辑封装在Lambda中。该机制实现了路径生成的解耦、灵活与高效,MergeTreeWriter只需在需要时调用工厂方法

2025-07-11 16:03:51 533

原创 Flink Exactly Once 和 幂等

Flink的Exactly-Once语义通过分布式快照和两阶段提交机制,确保数据在故障恢复时仅处理一次。分布式快照定期保存应用状态,而两阶段提交协调数据源与数据汇的事务,实现端到端一致性。基于处理时间的窗口操作是非幂等的,因处理时间的不确定性可能导致重算结果不同。事件时间则可保证窗口划分的确定性。Paimon作为流式数据湖存储,通过快照和原子提交机制解决写入幂等性问题,与Flink的Checkpoint机制协同工作。Paimon还利用SequenceNumber机制确保数据更新顺序,支持用户指定字段

2025-07-10 22:03:24 712

原创 揭秘Paimon 内存分页读写

本文详细解析了Paimon数据处理框架中的三个核心类:AbstractPagedOutputView、SimpleCollectingOutputView和AbstractPagedInputView/RandomAccessInputView。AbstractPagedOutputView采用模板方法模式,为跨页数据写入提供通用框架,将获取新页面的逻辑交由子类实现。SimpleCollectingOutputView是其具体实现,负责从内存池获取页面并收集所有使用过的内存页。

2025-07-10 10:34:25 721

原创 Paimon 原子提交实现

Paimon提交过程通过FileStoreCommitImpl实现,将文件变更转化为原子性快照,支持APPEND、COMPACT和OVERWRITE三种提交类型。核心提交流程包括:收集变更、分类处理、写入Manifest、生成ManifestList、最后原子提交Snapshot文件。对于并发控制,HDFS依靠其原子rename操作实现无锁提交,而对象存储则需依赖Hive/JDBC分布式锁。快照机制是Paimon实现ACID事务和时间旅行的基础。

2025-07-09 20:52:44 915

原创 Paimon StreamTableScan 和 snapshot Manager

Paimon的StreamTableScan是流式读取的核心接口,包含三个关键实现:DataTableStreamScan作为基础实现,负责全量与增量扫描及状态管理;LookupDataTableScan专为LookupJoin优化,继承前者功能;AuditLogStreamScan采用装饰器模式,包装基础实现以支持审计日志表的流式读取。三者构成分层体系,通过SnapshotManager高效管理快照文件,支持从指定点恢复、保存进度及通知完成等流式作业必需功能,确保数据一致性。

2025-07-09 19:05:06 847

原创 Paimon 元数据序列化和内存占用

本文详细分析了Paimon中各类元数据文件的序列化机制和存储结构。主要内容包括: ManifestEntry使用嵌套序列化方式,将DataFileMeta作为内部字段处理,通过ManifestEntrySerializer完成转换。 ManifestFile存储变更记录,采用层级结构:Snapshot→ManifestList→ManifestFileMeta→ManifestFile→ManifestEntry,实现高效元数据管理。 Snapshot采用JSON格式存储,包含指向ManifestList

2025-07-08 22:28:44 679

原创 Paimon本地表查询引擎LocalTableQuery详解

Paimon的LocalTableQuery通过本地缓存机制实现高效点查。它将远程数据文件拉取到TaskManager本地并建立索引,维护分区/桶结构的数据视图,支持动态更新和缓存管理。LocalTableQuery在计算节点本地缓存数据,性能高但资源消耗大;RemoteTableQuery通过独立QueryService集群提供RPC查询,资源消耗低但存在网络开销。Paimon QueryService巧妙地将LocalTableQuery能力服务化,启动RPC服务器共享查询资源

2025-07-08 22:11:09 726

原创 paimon.disk包:磁盘处理

Paimon的磁盘I/O系统通过分层设计实现高效的数据溢出(spill)管理。核心组件包括: 基础接口:FileIOChannel定义了文件通道的基本操作,包括ID获取、大小查询、关闭删除等。其内部类ID和Enumerator负责生成唯一文件名并实现负载均衡。 抽象实现:AbstractFileIOChannel作为骨架实现,处理文件生命周期管理,子类只需专注读写逻辑。BufferFileWriterImpl和BufferFileReaderImpl分别实现数据块的写入和读取。

2025-07-07 22:16:02 608

原创 Paimon LSM Tree Compaction 策略

Paimon的Merge-Tree压缩机制通过分层调度和策略选择实现高效数据管理。MergeTreeCompactManager:总调度中心。支持两种模式: 全量合并(Full Compaction):将所有文件合并到最高层级 常规合并:使用策略(如UniversalCompaction)智能选择文件 压缩策略: UniversalCompaction:基于文件数量、大小比例等指标选择合并文件 ForceUpLevel0Compaction:激进合并Level0文件,优化Lookup场景

2025-07-07 22:12:52 2314

原创 Paimon lookup核心过程:分级查找、二分和缓存创建(LookupFile)

Paimon中的LookupLevels是一个高效的键值查找引擎,核心功能是通过多层缓存机制在LSM-Tree中快速定位数据。它采用惰性缓存策略,首次查询远程数据文件时会下载并构建本地索引文件(LookupFile),使用Caffeine缓存管理生命周期。系统包含多层查找逻辑:从指定层级开始向上搜索,针对Level0采用全量遍历,更高层级使用二分查找优化。LookupFile封装了本地索引文件,提供基于Key的快速查询,并关联原始远程文件元数据。通过ValueProcessor策略接口支持多样化查询需求

2025-07-06 15:41:26 1120

原创 Paimon索引概述

Paimon索引设计分为三类:主键索引(数据物理有序存储)、文件内嵌索引(如Parquet/ORC的MinMax和BloomFilter)和二级索引(独立索引文件)。主键索引在写入L0文件和Compaction时自动建立;文件内嵌索引由底层文件格式写入器同步生成;二级索引主要在Compaction期间创建以提高效率。Paimon通过DataFileIndexWriter实现独立于文件格式的索引框架,支持多种索引类型,并根据索引大小决定嵌入元数据或生成独立索引文件。该框架采用组合模式管理不同类型的索引写入器

2025-07-06 15:14:20 654

原创 Paimon 高效哈希:MurmurHashUtils解析

MurmurHashUtils是Paimon项目中的高效哈希工具类,实现了MurmurHash3算法(32位版本)。该类采用final修饰且构造器私有,作为纯工具类使用。核心特性包括:使用Unsafe API直接操作内存提升性能;提供多种哈希方法支持字节数组、MemorySegment等不同输入;通过分块处理、尾部处理、最终混合三个阶段确保哈希质量。算法利用魔法常数C1/C2进行位混合,默认种子42,并确保结果为正数。特别适合哈希表、布隆过滤器等需要快速优质哈希的场景,是Paimon数据结构和算法的重要基础

2025-07-05 20:49:34 703

原创 Paimon 位图索引解析:高效等值查询的秘密( Bit-Sliced Index)

BitmapFileIndex采用RoaringBitmap32数据结构,适用于低基数列的等值查询,通过行号位图精准定位数据,并优化了单值存储空间。BitSliceIndexBitmapFileIndex采用位切片技术,专为数值型范围查询设计,通过分离正负数处理实现高效过滤。两种索引均采用延迟加载策略,并与数据文件强绑定。BitmapFileIndex的序列化过程更为复杂,通过特殊编码优化单值存储,而BitSliceIndex的序列化则相对直接。

2025-07-05 16:53:00 715

原创 Paimon 布隆过滤器索引

本文系统分析了布隆过滤器的核心原理及其在Paimon中的实现。首先推导了布隆过滤器的最优参数公式,包括位图大小m和哈希函数个数k的计算方法,并解释了当位图中0和1数量均衡时效率最高的信息论原理。然后详细解析了Paimon中的BloomFilterFileIndex类结构,说明其作为索引框架入口如何通过Writer和Reader实现布隆过滤器的构建与查询。最后深入剖析了底层BloomFilter64的实现,重点阐述其基于64位哈希的高效算法、Kirsch-Mitzenmacher优化技术以及轻量级Bitset

2025-07-04 22:07:15 767

原创 Paimon Lookup: LSM Tree Sort Block

Paimon主键表查找流程解析 Paimon采用LSM-Tree结构存储主键表数据,查找流程分为三层结构: 层级查找(宏观) 从Level0开始逐层向下查找 Level0文件间Key范围重叠,需遍历所有文件 Level1及以上文件Key范围有序不重叠,可二分查找 文件定位(中观) 对当前层级文件列表进行二分查找 利用文件元数据(minKey/maxKey)快速定位候选文件 为提升性能,采用多种优化:为Parquet主文件建立轻量级Lookup索引布隆过滤器快速过滤不存在Key数据块压缩 多级缓存

2025-07-04 16:18:24 712

原创 Paimon的LSM 包 和 LSM Tree的基本结构

Paimon的MergeTree包实现了核心的LSM-Tree结构,主要包含三个关键组件:写入路径、数据结构和压缩机制。MergeTreeWriter作为写入入口,将KeyValue记录缓存到WriteBuffer(如SortBufferWriteBuffer)并进行排序后刷盘生成L0层SST文件。Levels类管理LSM-Tree的多层级结构,其中L0层文件无序,L1+层文件有序不重叠。SortedRun封装一组有序且键不重叠的文件,是压缩的基本单元。

2025-07-03 20:11:29 996

原创 Paimon MergeTreeWriter:LSM Tree level0 SST的诞生

MergeTreeWriter是Apache Paimon写入链路的核心组件,采用LSM-Tree架构设计,负责单个分区分桶内的数据写入、合并和提交准备。其主要功能包括:1) 接收KeyValue形式的数据写入;2) 在缓冲区(SortBufferWriteBuffer)中进行排序和合并;3) 将有序数据整理为Level-0层SST文件;4) 管理合并(Compaction)流程优化文件结构;5) 生成变更日志(Changelog)支持流式读取。

2025-07-03 15:22:18 396

原创 Paimon MemStore写入本地磁盘前的Sort:外存归并

Paimon的BinaryExternalSortBuffer实现了高效的外部排序算法,包括两个阶段:首先将内存数据排序后溢写为磁盘文件(Sort and Spill),然后通过多路归并(Merge)生成全局有序结果。该组件采用最小堆管理多个输入流,BinaryMergeIterator负责执行K路归并,而AbstractBinaryExternalMerger则处理多轮归并调度。专用子类BinaryExternalMerger实现了BinaryRow的序列化/反序列化及比较逻辑。通过对象复用减少GC。

2025-07-02 20:16:28 876

原创 Paimon vs. HBase:全链路开销对比

Paimon与HBase在存储架构和性能表现上存在显著差异。Paimon采用列式存储和Flink Checkpoint机制,通过一次性构建LookupFile优化查询性能,其写入路径更轻量级,存储空间占用仅为HBase的1/3甚至更少。而HBase依赖WAL和复杂元数据,虽保证低延迟但持续开销较大。Paimon的设计哲学是用可控的一次性开销换取持续高效的分析性能,特别适合流式分析场景。在数据湖分析场景中,Paimon的整体资源消耗和效率通常优于HBase。

2025-07-02 17:06:31 969

原创 Paimon MemStore写入本地磁盘前的Sort:内存快排

本文详细解析了Paimon中LSM写入SST的内存排序机制设计,核心内容包括: 指针排序技术:通过BinaryIndexedSortable实现数据与索引分离,使用指针和范式化键进行轻量级排序,避免移动大块数据。 分层排序实现: BinaryInMemorySortBuffer:纯内存排序,采用快速排序优化 BinaryExternalSortBuffer:支持内存溢出到磁盘的外部排序 范式化键(NormalizedKey)加速比较 混合排序策略(快速排序+插入排序+堆排序)

2025-07-01 19:33:52 814

原创 Paimon写入流程:从本地到远程的三层架构

数据写入Paimon存储系统分为三层处理架构:1. 本地预处理层(SortBufferWriteBuffer) - 负责内存排序和本地磁盘溢写,生成有序数据迭代器;2. 分桶写入层(MergeTreeWriter) - 将预处理数据与远程存储的旧数据进行归并排序,生成新的SST文件写入远程存储;3. 事务提交层(Committer) - 收集文件变更信息,生成Manifest清单文件并通过原子性Snapshot文件完成事务提交。整个流程实现了从本地排序到远程存储的阶梯式处理,确保数据有序性和写入原子性。

2025-07-01 17:32:43 828

原创 Paimon LSM Tree Compaction核心:堆和败者树

SortMergeReaderWithMinHeap和SortMergeReaderWithLoserTree是Paimon中实现多路归并排序的两种核心实现。两者都用于合并多个已排序的数据流,但采用不同数据结构:MinHeap使用最小堆,每次调整需要约2logK次比较;LoserTree采用败者树,优化为约logK次比较。LoserTree通过状态机(State)和firstSameKeyIndex字段高效处理主键相同的记录分组,支持快速跳转优化。两种实现都遵循"取数-调整-补充"的循环

2025-06-30 16:14:20 2407

原创 Paimon 内存管理 MemorySegmentPool 核心解析

Paimon内存管理核心接口分析 MemorySegmentSource和MemorySegmentPool是Paimon内存管理的两个核心接口。MemorySegmentSource作为基础接口,定义了单向获取内存段的能力,仅提供nextSegment()方法来分配内存段,不涉及回收机制。MemorySegmentPool则扩展了池化管理功能,增加了returnAll()方法实现内存复用,并提供了pageSize()、freePages()等状态查询方法。 MemoryPoolFactory提供抢占机制。

2025-06-30 15:23:45 775

原创 揭秘Paimon核心:MemorySegment内存管理黑科技

Paimon内存管理核心组件解析 本文详细介绍了Paimon项目中的三个核心内存管理组件: MemorySegment:统一内存管理核心类,封装堆内/堆外内存操作,通过Unsafe API提供高性能访问,支持字节序控制和批量操作。 MemorySize:内存大小表示工具类,提供类型安全的内存配置处理,支持字符串解析、单位转换和算术运算,确保内存计算的准确性。 Buffer:轻量级内存容器,包装MemorySegment并跟踪有效数据大小,支持可变数据存储和NIO互操作。

2025-06-29 15:06:51 849

原创 Paimon核心I/O设计解析

Paimon的io包核心采用分层架构和工厂模式。文件写入基于FileWriter接口,SingleFileWriter负责单文件写入,RollingFileWriter实现自动分文件机制。设计亮点包括:统计信息收集(StatsCollectingSingleFileWriter)、索引管理(DataFileIndexWriter)和KeyValue专用处理(KeyValueDataFileWriter)。

2025-06-29 15:03:10 876

原创 Netty 揭秘CompositeByteBuf:零拷贝优化核心技术

CompositeByteBuf是Netty中实现虚拟缓冲区的核心类,通过将多个ByteBuf合并为单一逻辑视图来减少数据复制。其核心设计包括: 零拷贝优化:通过组合而非复制提升性能,保持底层数据物理隔离 分层索引系统:维护逻辑索引到物理索引的三层映射关键实现包括:使用Component内部类封装每个缓冲区的元数据通过二分查找+缓存优化索引定位提供consolidate()进行组件合并优化支持discardReadBytes()等细粒度内存回收

2025-06-28 21:23:35 1000

原创 Netty内存池化技术 PooledByteBufAllocator 深度解析

Netty的PooledByteBufAllocator采用分层内存池设计,通过PoolThreadLocalCache为每个线程提供本地缓存,减少锁竞争。核心组件包括管理堆/直接内存的PoolArena、4MB大小的PoolChunk,以及处理小内存的PoolSubpage。分配流程优先从线程缓存获取,未命中则访问PoolArena,并支持非池化回退。系统通过validateAndCalculate方法验证关键参数,确保内存结构安全。该设计实现了高效内存分配与回收,内置泄漏检测,通过多Arena负载均衡

2025-06-28 20:36:26 928

原创 Netty 的 PooledByteBuf与PooledHeapByteBuf​​

PooledByteBuf是Netty内存池化的核心,通过引用计数和线程缓存(PoolThreadCache)实现高效内存管理,支持堆/直接内存(PooledHeapByteBuf/PooledDirectByteBuf)。其生命周期包括分配(轻量级扩容)、零拷贝派生(retainedSlice)和释放(归还PoolArena)。PooledHeapByteBuf基于byte[],通过ObjectPool复用对象,与HeapArena协作完成内存分配,优化读写性能。两者共同构成Netty高性能内存体系。

2025-06-27 21:50:10 1008

原创 Netty堆内存字节缓冲区深度解析

摘要:UnpooledHeapByteBuf是Netty基于JVM堆内存的非池化字节缓冲区实现,采用byte[]作为底层存储,具有非池化设计、堆内存管理、引用计数等特点。其核心机制包括:1)通过System.arraycopy实现高效容量调整;2)零拷贝NIO缓冲区转换;3)索引边界控制确保安全访问。优化子类UnpooledUnsafeHeapByteBuf通过Unsafe API跳过数组初始化和边界检查提升性能。对比直接内存实现UnpooledDirectByteBuf,堆内存版本更适合高频创建的临时缓冲

2025-06-27 21:40:42 689

原创 Netty 引用计数抽象类 AbstractReferenceCountedByteBuf 详解

AbstractReferenceCountedByteBuf通过引用计数机制实现高效内存管理,其核心设计包括:1)使用volatile int refCnt字段存储编码后的引用计数(偶数表示活跃状态);2)通过ReferenceCountUpdater实现原子性操作,采用CAS机制保证线程安全;3)当引用计数归零时自动调用deallocate()释放资源;4)提供非阻塞式访问控制和优化路径。该实现结合模板方法模式与双重保障机制(AtomicIntegerFieldUpdater+Unsafe)

2025-06-26 22:13:28 892

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除