自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 一次cpu 跌底排查

早上一起来,服务cpu跌低了。登录机器,排查问题方法:1.执行命令 top (查看cpu占比比较大的进程pid),2.执行 top -Hp pid (查看对应进程 下面cpu占比比较大的 线程id(就是对应的pid))3. 用 printf "%x\n" (第2步找到的线程id) 转换成16进制的,应为线程id 在堆栈中有一个对应的16进制的nid4.执行 jstack pid | grep 'nid(步骤3中的nid)' -A 20 查看对应的线程的堆栈信息。 补充 jstack 命令

2022-06-28 20:51:17 487 1

原创 rocket mq的两种索引文件

消息文件commitLog:一个broker对应一组消息文件commitLog,所有topic的消息都存在commitLog中,写完一个继续写下一个索引文件consumeQueue:rocketMq中每个topic对应多个queue,每个queue对应一组索引文件consumeQueue,commitLog中的每条消息在consumeQueue中都对应一条索引数据,索引的key为消费位点,内容为commitLog中消息的位置信息。消费位点表示当前消费到第几条消息了,在rocketMq中,消费者都是按

2022-04-27 17:40:54 518

原创 dubbo

因为 RPC 和 HTTP 就不是一个层级的东西,所以严格意义上这两个没有可比性,也不应该来作比较,而题目问的就是把这两个作为比较了。HTTP 只是传输协议,协议只是规范了一定的交流格式,而且 RPC 是早于 HTTP 的,所以真要问也是问有 RPC 为什么还要 HTTP。RPC 对比的是本地过程调用,是用来作为分布式系统之间的通信,它可以用 HTTP 来传输,也可以基于 TCP 自定义协议传输。官网的一张图。首先注册中心和监控中心是可选的,你可以不要监控,也不要注册中心,直接在配置

2022-04-11 11:09:35 626

原创 redis 的缓存穿透&&淘汰策略

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。 解决方案: 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的.

2022-04-08 17:19:40 133

原创 hashMap

HashTable和ConcurrentHashMap的 共同特点 是 不允许 key 和 value 为 null,注意它们的 键值 都 不能是 null呀 ,而HashMap就比较随意,都可以是 null。hashmap1.7 扩容 void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[b...

2022-03-30 11:07:33 218

原创 快速排序 - 个人理解

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。该方法的基本思想是:1.先从数列中取出一个数作为基准数。2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。3.再对左右区间重复第二步,直到各区间只有一个数。虽然快速排序称为分治法,但分治法这三个字显然无法很好的概括快速排序的全部步骤。因此我的对快速排序作了进一步的说明:挖坑填数+分治法:个人理.

2022-03-28 16:02:42 81

原创 AQS 队列原理

Lock 使用范式synchronized 有标准用法,这样的优良传统咱 Lock 也得有,相信很多人都知道使用 Lock 的一个范式 Lock lock =newReentrantLock(); lock.lock(); try{ ... }finally{ lock.unlock(); } 标准1—finally 中释放锁既然是范式(没事不要挑战更改写法的那种),肯定有其理由,我们来看一下这个大家应该都会明白,在 fi...

2022-03-28 11:40:36 1743

原创 类加载&双亲委派原则

系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。加载类加载过程的第一步,主要完成下面3件事情: 通过全类名获取定义此类的二进制字节流 将字节流所代表的静态存储结构转换为方法区的运行时数据结构 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 连接 分为 验证 准备 解析验证文件格式验证 字节流是否符合class文件格式的规范元数据验...

2022-03-24 14:33:43 66

原创 jvm 堆一定是共享的吗?

JVM的内存结构中,比较常见的两个区域就是堆内存和栈内存(如无特指,本文提到的栈均指的是虚拟机栈),关于堆和栈的区别,很多开发者也是如数家珍,有很多书籍,或者网上的文章大概都是这样介绍的:1、堆是线程共享的内存区域,栈是线程独享的内存区域。2、堆中主要存放对象实例,栈中主要存放各种基本数据类型、对象的引用。但是,作者可以很负责任的告诉大家,以上两个结论均不是完全正确的。Java对象的内存分配过程是如何保证线程安全的?我们知道,Java是一门面向对象的语言,我们在Java中使用的对象都

2022-03-24 10:39:35 1734

原创 键入网址后,期间发生了什么?

1.浏览器做的第一步工作是解析 URL2.生产 HTTP 请求信息3.dns解析 查询服务器域名对于的 IP 地址4.DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈。IP 中还包括 ICMP 协议和 ARP 协议。 ICMP用于告知网络包传送过程中产生的错误以及各种控制信息。 ARP用于根据 IP 地址查询相应的以太网 MAC 地址 5.tcp 传输。...

2022-03-24 10:20:12 984

原创 http /tcp

HTTP 是一种超文本传输协议(Hypertext Transfer Protocol),HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范HTTP 主要内容分为三部分,超文本(Hypertext)、传输(Transfer)、协议(Protocol)。 超文本就是不单单只是本文,它还可以传输图片、音频、视频,甚至点击文字或图片能够进行超链接的跳转。 上面这些概念可以统称为数据,传输就是数据需要经过一系列的物理介质从一个端系统传送到另外一个.

2022-03-23 20:51:53 1021

原创 I/O 模型

内核态和用户态我们的电脑可能同时运行着非常多的程序,这些程序分别来自不同公司。谁也不知道在电脑上跑着的某个程序会不会发疯似得做一些奇怪的操作,比如定时把内存清空了。因此 CPU 划分了非特权指令和特权指令,做了权限控制,一些危险的指令不会开放给普通程序,只会开放给操作系统等特权程序。你可以理解为我们的代码调用不了那些可能会产生“危险”操作,而操作系统的内核代码可以调用。这些“危险”的操作指:内存的分配回收,磁盘文件读写,网络数据读写等等。如果我们想要执行这些操作,只能调用操作系统开放

2022-03-23 11:18:05 169

原创 零拷贝技术

DMA 技术,也就是直接内存访问(Direct Memory Access)技术。什么是 DMA 技术?简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务。 DMA 收到磁盘的信号,将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中,此时不占用 CPU,CPU 可以执行其他任务 传统的文件传输有多糟糕?如果服务端要提供文件传输的功能,我们能想到的最简单的方式是:将磁盘.

2022-03-22 20:22:55 162

原创 java 基础

什么是线程和进程?进程(Process) 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,进程是线程的容器。线程(thread)程序执行的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程基本不拥有系统资源,只有一些运行时必不可少的资源,比如程序计数器、寄存器和栈,进程则占有堆、栈。知道synchronized原理吗?synchronized是j.

2022-03-22 20:10:26 76

原创 mysql 为什么喜欢b+树

MySQL 的数据是持久化的,意味着数据(索引+记录)是保存到磁盘上的,因为这样即使设备断电了,数据也不会丢失。磁盘读写的最小单位是扇区,扇区的大小只有 512B 大小,操作系统一次会读写多个扇区,所以操作系统的最小读写单位是块(Block)。Linux 中的块大小为 4KB,也就是一次磁盘 I/O 操作会直接读写 8 个扇区。由于数据库的索引是保存到磁盘上的,因此当我们通过索引查找某行数据的时候,就需要先从磁盘读取索引到内存,再通过索引从磁盘中找到某行数据,然后读入到内存,也就是说查询过程中.

2022-03-21 15:15:04 114

原创 mysql mvcc是怎样实现隔离级别的

InnoDB的MVCC实现逻辑InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现的。一个保存了行的事务ID(DB_TRX_ID),一个保存了行的回滚指针(DB_ROLL_PT)。每开始一个新的事务,都会自动递增产 生一个新的事务id。事务开始时刻的会把事务id放到当前事务影响的行事务id中,当查询时需要用当前事务id和每行记录的事务id进行比较。MVCC只在REPEATABLE READ和READ COMMITIED两个隔离级别下工作。其他两个隔离级别都和 MVCC不兼容 ,因为RE

2022-03-21 14:42:07 840

原创 2pc 和 3pc

事务的基本概念:就是一个程序执行单元,里面的操作要么全部执行成功,要么全部执行失败,不允许只成功一半另外一半执行失败的事情发生。例如一段事务代码做了两次数据库更新操作,那么这两次数据库操作要么全部执行成功,要么全部回滚。事务的基本特性:我们知道事务有4个非常重要的特性,即我们常说的(ACID)。Atomicity(原子性):是说事务是一个不可分割的整体,所有操作要么全做,要么全不做;只要事务中有一个操作出错,回滚到事务开始前的状态的话,那么之前已经执行的所有操作都是无效的,都应该回滚到开始前

2022-02-25 18:11:38 601

原创 mysql 的刷盘策略

发现线上又很多简单的update语句出现300多ms的慢sql.慢sql排查,查看执行计划是走索引的,于是联系dba.dba更改了刷盘策略。innodb_flush_log_at_trx_commit 和 sync_binlogmysql的"双1验证"指的是innodb_flush_log_at_trx_commit和sync_binlog两个参数设置,这两个是是控制MySQL 磁盘写入策略以及数据安全性的关键参数。下面从参数含义,性能,安全角度阐述两个参数为不同的值时对db 性能,数据的.

2022-02-18 15:45:16 1707

原创 生产环境 遭遇 fastJson1.2.78 巨坑

昨天下午吃完一个苹果,再来一首王菲的《传奇》“只是因为在人群多看了她一眼”,就准备上线,刚开始一切顺利,但是上第6台机器机器的时候,突然咔咔咔的报警。一瞬间懵逼了。报警还原:我擦 这是什么鬼????。及时止损操作:停止上线,发现只有这台机器一直报错,马上进行机器摘流操作。排查问题:报警分析:Comparison method violates its general contract!就认识三个单词????猜一猜 大概是进行比较操作的时候没有遵循某种规范。根据报错栈信息定位 :A

2022-01-14 15:14:29 1801 3

原创 IO模型--多路复用

阻塞IO 和非阻塞IO 这两个概念是程序级别的。主要描述的是程序请求操作系统IO操作后,如果IO资源没有准备好,那么程序该如何处理的问题:前者等待;后者继续执行(但是使用线程一直轮询,直到有IO资源准备好了)。同步IO 和 异步IO,这两个概念是操作系统级别的。主要描述的是操作系统在收到程序请求IO操作后,如果IO资源没有准备好,该如何响应程序的问题:前者不响应,直到IO资源准备好以后;后者返回一个标记(好让程序和自己知道以后的数据往哪里通知),当IO资源准备好以后,再用事件机制返回给程序。同步

2021-12-31 16:12:12 1624

原创 泛型的擦除

List<String> l1 = new ArrayList<String>();List<Integer> l2 = new ArrayList<Integer>(); System.out.println(l1.getClass() == l2.getClass());请问,上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学应该能够答出来,而对泛型有所了解,但是了解不深入的同学可能会答错。正确答案是 true。什么是...

2021-12-27 14:39:08 192

原创 redis 如何实现延迟队列

Sorted Set了。我们可以把任务的描述序列化成字符串,放在Sorted Set的value中,然后把任务的执行时间戳作为score,利用Sorted Set天然的排序特性,执行时刻越早的会排在越前面。这样一来,我们只要开一个或多个定时线程,每隔一段时间去查一下这个Sorted Set中score小于或等于当前时间戳的元素(这可以通过zrangebyscore命令实现),然后再执行元素对应的任务即可。当然,执行完任务后,还要将元素从Sorted Set中删除,避免任务重复执行。如果是多个线程去轮询这个S

2021-12-14 15:33:44 873

原创 mysql 不建议delete?

1.mysql delete物理删除既不能释放磁盘空间。MySQL内部不会真正删除空间,而且做标记删除,即将delflag:N修改为delflag:Y,commit之后会会被purge进入删除链表,如果下一次insert更大的记录,delete之后的空间不会被重用,如果插入的记录小于等于delete的记录空会被重用.2.会产生大量碎片。导致索引频繁分裂,影响SQL执行计划的稳定性,同时在碎片回收时,会耗用大量的CPU,磁盘空间,影响表上正常的DML操作。碎片的回收对于InnoDB的表,可

2021-12-09 20:24:28 1077

原创 threadLocal之内存泄露

内存泄露内存泄露为程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光,广义并通俗的说,就是:不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。强引用与弱引用强引用,使用最普遍的引用,一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样

2021-12-08 10:36:52 634

原创 mysql 覆盖索引

辅助索引辅助索引也称为二级索引,索引中除了存储索引列外,还存储了主键id,对于user_name的索引idx_user_name(user_name)而言,其实等价于idx_user_name(user_name, id),MySQL会自动在辅助索引的最后添加上主键id索引回表上面证明了辅助索引包含主键id,如果通过辅助索引列去过滤数据有可能需要回表,举个例子:业务需要通过用户名user_name去查询用户表users的信息,业务接口对应的SQL:select user_id, us

2021-12-06 15:43:24 982

原创 mysql 架构以及各种存储引擎的索引区别

一、MySQL架构和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。 连接层:最上层是一些客户端和连接服务。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接.

2021-11-30 16:30:48 660

原创 mysql 为什么默认的隔离级别是RR,间隙锁机制

首先查看mysql的当前事务隔离级别:select @@tx_isolation;查看全局的事务隔离级别:SELECT @@global.tx_isolation;修改事务隔离级别MySQL 提供了 SET TRANSACTION 语句,该语句可以改变单个会话或全局的事务隔离级别。语法格式如下:SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATAB

2021-11-29 20:02:38 2598

原创 算法-时间复杂度和空间复杂度

简单说就是,同一个功能别人写的代码跑起来占内存 100M,耗时 100 毫秒 你写的代码跑起来占内存 500M,耗时 1000 毫秒,甚至更多所以衡量代码好坏有两个非常重要的标准就是:运行时间和占用空间,就是我们后面要说到的时间复杂度和空间复杂度,也是学好算法的重要基石 这也是会算法和不会算法的攻城狮的区别、更是薪资的区别,因为待遇好的大厂面试基本都有算法可能有人会问:别人是怎么做到的?代码没开发完 运行起来之前怎么知道占多少内存和运行时间呢?确切的占内用存或运行时间确实算不出来,而且同

2021-11-24 15:17:51 383

原创 redis分布式锁

普通方式获取锁获取锁(unique_value可以是UUID等)SET resource_name unique_value NX PX 30000 释放锁(lua脚本中,一定要比较value,防止误解锁)if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end如果在删除锁的时候不用lua,而是用java代码如下if(redisValue.e

2021-11-23 15:10:05 622

原创 mysql 大数据扫表优化

问题:单表200w 需要根据时间去扫全表。数据表 :order 索引:create_time优化前:select * from order where create_time < '2021-11-18' and status = 8;mysql范围查询范围查询如果where后面查询的数据量大于全表的15%。mysql的执行优化器会默认放弃索引而扫描全表数据。从而会经常出现timeout.优化后:select * from order where id > xxx...

2021-11-18 20:45:59 2205

原创 mysql 事务

事务特性:原子性,一致性,隔离性,持久性。事务想要的效果:可靠性和并发处理可靠性:数据库在insert update异常或者数据库宕机时保证数据修改操作的前后一致性。需要知道数据修改前和修改后的状态。所以就有了redo log和undo log。并发处理:当多个请求对数据库进行操作的时候,多个操作之前相互隔离,避免出现读到脏数据。实现事务的三个技术:日志(redo/undo log),锁技术,mvcc1.redo log什么是redol log ?redo log叫做重做日志,是

2021-11-17 20:24:38 416

原创 redis数据结构重点总结

简单动态字符串Redis 只会使用 C 字符串作为字面量, 在大多数情况下, Redis 使用 SDS (Simple Dynamic String,简单动态字符串)作为字符串表示。 比起 C 字符串, SDS 具有以下优点: 常数复杂度获取字符串长度。 杜绝缓冲区溢出。 减少修改字符串长度时所需的内存重分配次数。 二进制安全。 兼容部分 C 字符串函数。 2链表链表被广泛用于实现 Redis 的各种功能, 比如列表键, 发布与订阅, 慢查询, 监视器, 等等。 每个链...

2021-10-20 11:35:14 57

原创 mysql 的大坑

著名的坑:mysql数据库本身能够设置连接超时时间wait_timeout,如果连接池的连接的最大空闲时间大于这个阈值,则连接可能已经被因数据库断掉而失效了,但该连接在池中还能够被使用。此时使用此连接时就会报错。对于这种情况有三种解决方式:设置最大空闲时间小于数据库的连接超时时间,在数据库连接超时之前该连接就能够被连接池回收; 使用空闲连接检测,有些连接池会有testOnBorrow或者testOnReturn配置,在使用或者放回连接时检测连接时候有效。 keep alive机制,可以设置一个无意义

2021-10-19 20:55:21 160

原创 copy on write

Copy On Write技术实现原理:fork()之后,kernel把父进程中所有的内存页的权限都设为read-only,然后子进程的地址空间指向父进程。当父子进程都只读内存时,相安无事。当其中某个进程写内存时,CPU硬件检测到内存页是read-only的,于是触发页异常中断(page-fault),陷入kernel的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份。Copy On Write技术好处是什么?COW技术可减少分配和复制大量资

2021-09-29 17:25:37 105

原创 redis rdb和aof持久化方式

rdbRDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会重新加载dump.rdb文件的数据到内存当中恢复数据。1.save命令save命令是一个同步操作。当客户端向服务器发送save命令请求进行持久化时,服务器会阻塞save命令之后的其他客户端的请求,直到数据同步完成。2. bgsave与save命令不同,bgsave命令是一个异步操作。当客户端发服务发出bgsave命令时,R

2021-09-27 11:08:46 66

原创 静态代码块执行时间点 和 常量的初始化时间点

静态代码块执行时间点错误认识:刚开始误认为JAVA静态代码块在类被加载时就会自动执行。正确:在类的初始化阶段执行解释类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。当一个类被主动使用时,Java虚拟就会对其初始化,如下六种情况为主动使用:当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等) 当调用某个类的静态方法时 当使用某个类或接口的静态字段时 当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的

2021-09-23 17:49:09 341

原创 redis 数据类型

SDS 与 C 字符串的区别:1 常数复杂度获取字符串长度因为 C 字符串并不记录自身的长度信息, 所以为了获取一个 C 字符串的长度, 程序必须遍历整个字符串, 对遇到的每个字符进行计数, 直到遇到代表字符串结尾的空字符为止, 这个操作的复杂度为O(N)。和 C 字符串不同, 因为 SDS 在len属性中记录了 SDS 本身的长度, 所以获取一个 SDS 长度的复杂度仅为O(1)。举个例子, 对于图 2-5 所示的 SDS 来说, 程序只要访问 SDS 的len属性...

2021-09-13 20:26:17 95

原创 4种经典限流算法讲解

固定窗口限流算法首先维护一个计数器,将单位时间段当做一个窗口,计数器记录这个窗口接收请求的次数。当次数少于限流阀值,就允许访问,并且计数器+1 当次数大于限流阀值,就拒绝访问。 当前的时间窗口过去之后,计数器清零。假设单位时间是1秒,限流阀值为3。在单位时间1秒内,每来一个请求,计数器就加1,如果计数器累加的次数超过限流阀值3,后续的请求全部拒绝。等到1s结束后,计数器清0,重新开始计数。如下图:缺点:1.在临界点有可能出现毛刺2 .临界问题:假设限流阀值为5个请求,单位时..

2021-09-09 17:28:36 221

原创 rocketmq push和pull两中方式的区别

push实际上底层是用的pull总结: RocketMq的推模式不是严格意义上的推,是通过后台启动异步线程,一个queue构建一个pullRequest, 异步的去请求的拉模式,只不过是通过broker端阻塞(默认阻塞15秒)的方法,达到了推模式的效果。 其实就是长轮询模式,哈哈同时,rocketMq通过流量控制模块(消息数量(1000),消息大小(100MB),offSet跨度(并行消费))来控制消费者这一边的压力,不至于消费慢,被后台异步线程给压死。rocketMq的流量控制,pu...

2021-08-04 15:22:42 2735

转载 什么是mmap

平时在面试中你肯定会经常碰见的问题就是:RocketMQ为什么快?Kafka为什么快?什么是mmap?这一类的问题都逃不过的一个点就是零拷贝,虽然还有一些其他的原因,但是今天我们的话题主要就是零拷贝。传统IO在开始谈零拷贝之前,首先要对传统的IO方式有一个概念。基于传统的IO方式,底层实际上通过调用read()和write()来实现。通过read()把数据从硬盘读取到内核缓冲区,再复制到用户缓冲区;然后再通过write()写入到socket缓冲区,最后写入网卡设备。整个过程发生了

2021-08-03 16:47:01 356

空空如也

空空如也

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

TA关注的人

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