- 博客(88)
- 收藏
- 关注
原创 JUC(四)——线程中断/JMM/happens-before
本文摘要: 线程中断是一种协作机制,通过interrupt()、isInterrupted()和interrupted()三个方法实现,但需要线程主动检查中断状态并响应。相比被弃用的stop()方法更安全。LockSupport提供了更灵活的线程阻塞/唤醒机制,无需加锁且可逆序使用。Java内存模型(JMM)定义了多线程环境下共享变量的可见性、原子性和有序性规则,通过happens-before原则确保操作顺序和结果可见性。JMM与CPU缓存机制协同工作,在保证线程安全的同时提升性能。文章还对比了不同同步机
2026-01-27 11:49:33
622
原创 JUC(三)——synchronized
本文介绍了Java中synchronized锁的核心概念和实现原理。synchronized可以修饰实例方法和静态方法,实例方法锁的是当前对象(this),静态方法锁的是类对象(Class)。文章通过代码示例展示了不同加锁方式的线程行为差异,并解释了字节码层面的实现机制(monitorenter/monitorexit指令和ACC_SYNCHRONIZED标志)。此外还讨论了公平锁与非公平锁的区别、可重入锁特性以及死锁问题。最后指出synchronized默认采用非公平锁策略以提高性能,并提供了排查死锁的方
2026-01-27 11:49:24
709
原创 JUC(二)——CompletableFuture
摘要:本文分析了CompletableFuture相对于FutureTask的优势。FutureTask存在get()方法阻塞、资源消耗大等缺点,而CompletableFuture通过实现CompletionStage接口,支持链式异步编程。其核心方法如thenApply和thenAccept可实现任务结果的非阻塞处理,通过supplyAsync方法提交任务后,可灵活选择同步或异步的后续处理。CompletableFuture采用类似递归的思路,每个阶段新建对象保存值,利用线程池执行任务,避免了Futur
2026-01-13 09:46:45
628
原创 JUC(一)——FutureTask
本文介绍了Java并发编程中的几个关键概念:1.用户线程与守护线程的区别,守护线程需显式声明并随用户线程结束;2.链式编程的实现原理,通过返回this实现方法链式调用;3.函数式编程和lambda表达式的使用;4.Stream流式编程结合链式和函数式特性;5.FutureTask的实现机制,通过封装Callable任务获取异步计算结果。文章采用杂志式风格讲解,内容涵盖JUC基础但未深入FutureTask缺点,留待下期探讨。
2026-01-13 09:46:26
717
原创 Redis(十八)——底层数据结构(三)
Redis底层数据结构解析:IntSet和RadixTree IntSet是Redis用于存储整数集合的紧凑结构,采用有序数组实现,支持二分查找(O(logn)),内存占用低但插入/删除需移动元素(O(n))。当元素超限或含非整数时自动转为哈希表。 RadixTree(基数树)是Redis 5.0+用于Stream类型的高效字符串存储结构,通过压缩单子节点路径优化普通前缀树,节省空间同时保持快速查找特性。 两种结构分别针对整数集合和字符串集合场景优化,体现了Redis根据不同数据类型特点选择最优底层实现的策
2025-12-24 11:10:28
731
原创 Redis(十七)——底层数据结构(二)
Redis 7.0引入了ListPack作为新型紧凑内存数据结构,用于替代ZipList并解决其连锁更新问题。ListPack优化了内存布局,将prevlen改为backlen(自身长度),使增删改查操作只需修改当前元素长度。它应用于Hash(小哈希)、ZSet(小有序集合)、QuickList节点和Stream消息等场景。与ZipList相比,ListPack牺牲了部分反向遍历性能但提升了整体稳定性。此外,Redis中ZSet使用跳表(SkipList)实现范围查询功能,而HashTable则作为基础数据
2025-12-24 11:10:23
857
原创 Redis(十六)——底层数据结构(一)
Redis底层数据结构解析:SDS、LinkedList、ZipList与QuickList Redis采用多种底层数据结构实现其数据类型,主要包括: SDS(简单动态字符串) 所有字符串类型的基础结构 特点:O(1)长度获取、二进制安全、自动扩容 空间预分配和惰性释放机制提升性能 LinkedList(双向链表) 早期List类型的实现 现仅作为QuickList内部组件使用 每个节点存储前后指针,内存利用率低 ZipList(压缩列表) 紧凑连续内存结构 通过prevlen字段实现双向访问 存在连锁更新
2025-12-22 16:38:27
958
原创 Redis(十五)——内存过期/淘汰策略
Redis内存管理与淘汰策略摘要 Redis内存管理通过maxmemory参数配置(默认0,64位系统可用75%机器内存)。内存满时会触发OOM错误。为防止内存溢出,Redis提供三种主动过期策略:1)立即删除(影响性能);2)惰性删除(空间浪费);3)定期删除(平衡方案,默认每秒检查20个key)。内存淘汰策略则被动触发,包含8种方式分为5类:不淘汰(noeviction)、LRU类(最近最少使用)、LFU类(最不常用)、随机类和TTL类(剩余时间最短)。不同策略适用于不同场景:缓存系统推荐allkeys
2025-12-22 16:38:22
682
原创 Redis(十四)——分布式锁
Redis分布式锁是一种业务锁,与数据库锁不同,它锁定的是业务而非数据。相比Java本地锁,Redis锁支持分布式场景。关键特性包括:互斥性、高可用性、防死锁(超时机制)、防误删(唯一标识)和可重入性。实现方式从早期的SETNX+EXPIRE(非原子)演进到SET NX EX命令(原子操作)。Redisson框架通过看门狗机制(自动续期)和Lua脚本优化了锁管理,而RedLock算法(多节点加锁)因主从同步问题逐渐被WAIT命令方案替代。对于强一致性场景,推荐使用ZooKeeper的临时节点机制。分布式锁的
2025-12-10 11:48:25
886
原创 Redis(十三)——缓存预热/穿透/击穿/雪崩
本篇主要讲的就是缓存的4种情况,下面是表格总结:缓存问题产生原因解决方案缓存更新方式数据变更、缓存时效性同步更新、失效更新、异步更新、定时更新缓存不一致同步更新失败、异步更新延迟增加重试、补偿任务、最终一致性缓存穿透恶意攻击、查询不存在数据空对象缓存、布隆过滤器(BloomFilter)缓存击穿热点key失效、高并发访问互斥更新、随机退避、差异失效时间缓存雪崩缓存服务挂掉、大量key同时失效快速失败熔断、主从模式、集群模式。
2025-12-10 11:48:19
779
原创 Redis(十二)——布隆过滤器/布谷鸟过滤器
摘要: 布隆过滤器与布谷鸟过滤器是两种高效的概率型数据结构,用于快速判断元素是否存在。布隆过滤器通过位数组和多个哈希函数实现,具有空间效率高(约11.4MB可存储1000万元素)、查询快(O(k)时间)的特点,但存在误判且不支持删除。布谷鸟过滤器改进为支持删除,通过指纹哈希和踢出策略实现更高空间利用率(固定指纹大小)和更低误判率,查询仅需检查2个位置(O(1))。布隆适合简单场景(如缓存穿透防护),布谷鸟则适用于需删除或高精度场景。两者选择需权衡误判率、内存和功能需求。
2025-11-27 15:36:05
1135
原创 Redis(十一)——业务统计
本文介绍了亿级流量系统中的四种统计方法:1)聚合统计(并集、交集、差集);2)排序统计(如热销榜);3)二值统计(是/否判断);4)基数统计(去重统计)。详细解析了UV、PV、DAU、MAU等关键指标,并演示了HyperLogLog(近似基数统计)、Bitmap(签到统计)和GEO(地理位置)三种Redis数据结构的具体应用场景及操作方法。重点比较了不同统计方法的适用场景,如HyperLogLog以0.81%误差换取内存效率,Bitmap适合二值记录但需注意内存消耗。文章通过实际Redis命令示例,展示了如
2025-11-27 15:36:01
947
原创 Redsi(十)——缓存双写
本文探讨了缓存双写(Redis+MySQL)场景下的数据一致性问题及解决方案。首先分析了同步和异步两种双写策略的优缺点:同步方式保证强一致性但性能较低,异步方式吞吐量高但存在数据不一致风险。接着阐述了缓存击穿、穿透、雪崩三种异常情况及其危害。针对这些问题,提出了双检加锁方案来避免数据库过载。然后详细比较了四种缓存更新策略,重点推荐"先更新数据库再删除缓存"的最终一致性方案,并介绍了延迟双删和看门狗机制作为补充保障。最后提及了Canal工具通过监听binlog实现数据同步解耦的方案。全文系
2025-11-24 17:48:16
1180
原创 Redis(九)——BigKey与MoreKey
Redis线上环境需禁用keys*、flushdb等危险命令,因其会导致主线程长时间阻塞。可通过配置文件rename-command禁用这些命令。替代keys*可使用SCAN命令分批次查询。BigKey指值过大或成员过多的键(如String>10KB或集合>5K成员),会导致阻塞、网络拥堵等问题;MoreKey指相同前缀键过多(>10万),造成内存碎片化。删除BigKey应采用渐进式方法(集合类型先删成员再删键),并通过lazyfree配置实现异步删除优化。可使用redis-cli --b
2025-11-24 17:48:08
1211
原创 Redis(八)——多线程与单线程
Redis采用单线程处理用户请求,但自Redis4起引入后台多线程(如RDB/AOF持久化、异步删除等)。Redis6进一步优化网络IO瓶颈,采用多线程处理网络请求,但核心读写仍保持单线程。其高性能源于内存操作、高效数据结构、IO多路复用及非阻塞IO机制。单线程架构简化开发并避免锁竞争,而多线程改进解决了大Key删除阻塞和网络吞吐瓶颈问题。Redis6/7默认关闭网络IO多线程,需手动配置开启。整体上Redis通过混合线程模型平衡性能与开发复杂度。
2025-11-19 17:09:32
928
原创 Redis(七)——集群
Redis集群采用哈希槽分区实现数据分片,将16384个槽位均匀分配给节点,支持动态扩容缩容且无需停服。相比一致性哈希和简单取模法,哈希槽在数据均衡、扩展性、运维难度等方面表现更优。集群自带故障转移机制,客户端可连接任意节点自动重定向。但需注意异步复制可能导致数据丢失,且mget需使用{}确保同槽位访问。集群理论最大支持16384节点,但官方建议控制在1000以内以降低网络开销和维护成本。
2025-11-19 17:09:28
1194
原创 redis(五)——管道、主从复制
Redis管道与主从复制是两种不同的优化技术。管道是客户端优化技术,通过批量发送命令减少网络往返时间,但不保证原子性;而事务则是服务端功能,通过MULTI/EXEC保证原子性执行。主从复制通过slaveof/replicaof配置实现读写分离,主机负责写、从机负责读,使用RDB和命令缓存实现数据同步,存在延迟和故障切换需手动处理的问题。两者分别针对不同场景优化:管道解决网络延迟,主从复制实现数据冗余和读写分离。
2025-11-14 14:54:46
964
原创 Redis(四)——事务
本文对比Redis和MySQL事务的核心差异:Redis事务本质是批量执行命令的队列(MULTI/EXEC机制),不提供完整ACID特性,缺乏隔离性和回滚机制,仅通过WATCH实现乐观锁来防止并发冲突;而MySQL事务具备完整ACID支持,采用悲观锁和MVCC保证隔离性。Redis单线程架构虽避免脏读/幻读,但仍需WATCH解决"超卖"等数据一致性问题。文中通过余额扣款案例演示Redis乐观锁的工作机制,强调WATCH-MULTI-EXEC组合的实际应用场景及注意事项,指出Redis事务
2025-11-06 18:10:45
598
原创 Redis(三)——RDB、AOF
Redis提供RDB和AOF两种持久化方案:RDB通过定时快照保存全量数据,默认配置自动触发保存条件,恢复速度快但可能丢失较多数据;AOF记录写操作日志,数据安全性更高但恢复较慢,Redis7优化为base+incr文件结构提升启动速度。两者可单独或混合使用,混合模式下RDB存储基础数据,AOF记录增量操作。纯缓存模式则关闭持久化以提升性能。数据恢复时优先使用AOF文件,官方提供redis-check工具检测修复损坏文件。生产环境建议根据业务需求选择合适的持久化策略,并配合备份机制确保数据安全。
2025-11-04 17:49:18
1461
原创 Redis(二)——数据类型二
Redis提供了丰富的地理空间数据类型(GEO),基于ZSet实现,支持地理位置存储和查询。核心命令包括GEOADD(添加位置)、GEOPOS(获取坐标)、GEODIST(计算距离)等,适用于地图相关应用如外卖、租房等。此外还介绍了发布订阅(Pub/Sub)和消息流(Streams)类型,Pub/Sub适合实时通知,Streams则是Redis5.0引入的持久化消息队列。最后总结了各数据类型的最大成员数限制,均约42亿个,以及各自的核心添加命令。
2025-11-03 16:06:34
1036
原创 Redis(一)——数据类型一
Redis常用数据类型及连接方式摘要 Redis支持多种数据类型,包括: String:最基础类型,支持设置过期时间和条件操作 List:双向链表,两端操作高效 Set:无序不重复集合 Zset:有序集合,按分数排序 Hash:键值对存储 Bitmaps:位图,节省空间 HyperLogLog:基数统计,占用空间固定 连接方式: 默认连接:redis-cli 指定端口:redis-cli -p 6379 远程连接:redis-cli -h IP -p PORT 密码连接:redis-cli -a PASSW
2025-10-30 15:36:00
936
原创 Mysql杂志(三十六)——Relay Log与主从同步、数据库备份恢复
MySQL主从复制中Relaylog是关键中间环节,负责将主库binlog写入从库执行。主从架构存在延迟问题,异步复制延迟最高,半同步复制保证至少一个从库数据一致,组复制(MGR)则确保从库间强一致性。数据库备份分为物理备份(二进制文件)和逻辑备份(SQL文本),常用mysqldump命令进行逻辑备份,支持多种格式和参数配置,恢复时可通过mysql命令行或客户端执行备份文件。备份时建议包含存储过程、触发器等完整数据,并记录binlog位置以便恢复。
2025-10-29 14:16:45
960
原创 Mysql杂志(三十五)——Bin log
MySQL Binlog是记录数据库所有DDL和DML操作的日志文件,主要用于主从复制和数据恢复。日志文件默认1GB大小,以事务为单位记录,可能超过限制。Binlog有三种格式:ROW(记录行变更,安全但占用空间)、STATEMENT(记录SQL语句,空间小但可能锁表)和MIXED(混合模式)。查看Binlog可使用mysqlbinlog工具或SHOW BINLOG EVENTS命令,支持按时间、位置、数据库等条件查询和恢复数据。重要参数包括log_bin(总开关)、binlog_format(日志格式)、
2025-10-24 16:13:45
957
原创 Mysql杂志(三十四)——MVCC、日志分类
本文详细介绍了MySQL的MVCC机制和各类日志系统。MVCC通过ReadView实现非锁定读,解决脏读和不可重复读问题,核心是事务ID检查和undo log版本链。MySQL日志分为事务日志(redo/undo log)、复制日志(binlog/relay log)和操作日志(error/slow/general log),各自承担崩溃恢复、主从复制和故障诊断等功能。其中慢查询日志和错误日志对性能优化尤为重要。文章解析了ReadView的工作流程和各类日志的特性,为理解MySQL事务机制和运维管理提供了实
2025-10-22 16:07:51
747
1
原创 Mysql杂志(三十三)——锁
本文主要介绍了数据库中的各种锁机制及其应用场景。从锁的粒度来看,可分为表锁、页锁和行锁;从操作类型区分,有读锁和写锁;从加锁态度分为悲观锁和乐观锁;从加锁方式分为显式锁和隐式锁。重点分析了表级锁(IS、IX、MDL锁)、行锁(记录锁、间隙锁、临键锁等)的特性及作用,并比较了不同锁的并发性能、资源消耗和死锁风险。文章还特别介绍了MySQL 8.0新增的谓词锁和InnoDB的隐式锁机制,最后强调锁粒度与并发性能的权衡关系:粒度越大并发越低但死锁风险小,反之则并发高但管理开销大。
2025-10-17 17:03:56
712
原创 Mysql杂志(三十二)——redo日志、undo日志
摘要:MySQL通过ACID特性保障数据一致性,其中redo日志(物理日志)和undo日志(逻辑日志)是关键实现机制。redo日志采用WAL预写机制,确保操作持久性,包含buffer刷盘的三种策略(0/1/2)。undo日志存储于回滚段(默认128个区),记录事务修改前的数据快照,支持事务回滚和MVCC。系统通过purge线程清理过期undo记录,并通过redo/undo日志协同工作保障崩溃恢复和事务原子性。这两种日志与事务ID、回滚指针等机制共同维护了MySQL的强一致性特征。
2025-10-15 11:58:52
1211
原创 Mysql杂志(三十一)——Join连接算法与子查询、排序优化
MySQL Join连接算法与查询优化摘要: MySQL提供多种Join算法:1)嵌套循环连接(默认算法),含简单循环和索引优化版本;2)块嵌套循环通过内存缓冲优化无索引连接;3)哈希连接(8.0+)专用于大表等值查询;4)批量键访问优化二级索引回表。子查询优化建议转为JOIN、条件下推和使用EXISTS。排序优化包括合理使用LIMIT、匹配索引顺序,以及根据内存情况选择单路(全加载)或双路(分批)排序算法。核心原则是减少数据扫描量,最小化临时表使用,合理利用索引降低I/O开销。
2025-10-11 15:17:12
883
原创 Mysql杂志(三十)——索引失效情况
本文分析了MySQL索引失效的常见情况及优化建议。主要失效场景包括:违反最左前缀原则、对索引列使用函数/计算、使用不等于(!=或<>)或NOT IN、LIKE通配符开头、隐式类型转换、OR连接非索引列等。文章还探讨了个人认为不会失效的情况(范围查询和SELECT *),并对比了四种EXPLAIN命令的功能差异。最后提供了优化方案,如使用UNION替代OR、避免类型转换、合理设计索引等,帮助开发者提升查询性能。
2025-10-10 17:28:06
1012
原创 Mysql杂志(二十九)——EXPLAIN FORMAT = JSON
本文详细解析了JSON格式的MySQL执行计划,相比传统EXPLAIN提供了更丰富的信息。主要内容包括:1)目录结构说明,重点解释不同SQL操作对应的标签类型;2)字段解析,涵盖基础信息、成本估算、表访问、行数预估、列使用、额外操作等关键指标;3)特别说明索引下推(ICP)等优化技术,以及排序、连接等操作的具体表现。文章建议先理解基础EXPLAIN再看此进阶内容,强调执行计划数据是预估而非实际值,需结合多个指标综合评估SQL性能。
2025-10-09 13:53:16
1077
原创 Mysql杂志(二十八)——EXPLAIN执行计划
SQL执行计划是衡量查询性能的重要工具,通过分析执行计划中的关键列可以判断查询是否高效使用索引、预估扫描行数等核心指标。主要关注列包括:id(执行顺序)、select_type(查询类型)、type(访问类型,应避免ALL全表扫描)、key(实际使用索引)、rows(预估扫描行数)和Extra(附加执行信息)。其中type列尤为重要,性能从优到差排序为system>const>eq_ref>ref>range>index>ALL。优化时应重点关注Extra列中的警告信息如
2025-09-30 10:07:41
1081
原创 Mysql杂志(二十七)——数据库状态
MySQL数据库监控可以通过系统变量快速排查基础问题,主要关注六个关键指标:1)连接和并发参数判断连接池需求;2)查询效率指标配合慢查询日志优化SQL;3)缓冲池命中率评估内存效率;4)磁盘I/O指标判断读写压力;5)锁竞争参数发现死锁;6)主从延迟监控复制状态。使用SHOW GLOBAL STATUS命令可查看400多项系统状态,这些全局统计适用于整个MySQL服务器。注意该方法适合基础监控,复杂问题需结合其他工具分析。
2025-09-29 11:07:12
962
原创 Mysql杂志(二十六)——索引设计原则
数据库索引优化要点:1.为具有唯一性(主键、外键等)和频繁查询条件的字段建立索引;2.经常排序/分组/去重的字段应考虑索引;3.连表查询需为关联字段建索引;4.长字符串可使用前缀索引;5.避免冗余索引,控制索引数量(建议不超过6个);6.联合索引和单索引需根据实际场景选择;7.增删改操作需权衡索引维护成本。合理使用索引能显著提升查询性能,但要避免过度索引影响写入效率。
2025-09-28 09:33:49
551
原创 Mysql杂志(二十五)——降序索引、隐藏索引
MySQL 8.0引入了降序索引和隐藏索引两大特性。降序索引通过逆向存储数据(4→3→2→1),优化了按降序字段(如销量、时间)查询的性能,比普通升序索引减少反向扫描开销。隐藏索引允许将索引标记为不可见而不删除,主要用于索引删除前的风险评估和性能测试,仍会维护唯一约束但不会被查询优化器使用。这两项特性分别解决了特定查询场景的性能优化和索引管理中的风险控制问题。
2025-09-26 09:32:00
883
原创 Mysql杂志(二十四)——区、段、碎片区、表空间
InnoDB存储引擎通过多级存储结构优化数据库性能:区(Extent)作为1MB的物理单元,将随机I/O转化为顺序I/O,提高预读效率;段(Segment)作为逻辑管理单元,实现数据与索引的分类管理;碎片区(Fragment Extent)针对小表优化空间利用率;表空间则作为核心容器整合这些结构。系统表空间集中管理关键功能如数据字典、UNDO日志等,而独立表空间则为每个表提供专属存储。这种分层设计在物理连续性、逻辑管理、空间利用和I/O性能之间取得平衡,实现了"以空间换时间"的优化目标。
2025-09-25 09:29:40
1071
原创 Mysql杂志(二十三)——行格式
本文对比分析了InnoDB的四种行格式:REDUNDANT、COMPACT、DYNAMIC和COMPRESSED。REDUNDANT兼容旧版本但空间利用率低;COMPACT是5.6-8.0的默认格式,在空间效率和性能间取得平衡;DYNAMIC针对大对象优化,5.7+默认,完全溢出存储;COMPRESSED通过压缩节省40-50%空间,但增加CPU开销。每种格式在记录头、事务字段等基础结构相似,主要差异在NULL处理、溢出管理和压缩支持。选择需考虑数据类型、MySQL版本和性能需求,如OLTP系统适合COMP
2025-09-24 09:29:07
1170
原创 Mysql(二十二)——InnoDB页结构
InnoDB页结构详解:16KB页由文件头、页头、用户记录、页目录和文件尾组成。文件头包含页号、校验和、前后页指针等关键信息(占38字节);页头记录槽位数、空闲空间、事务ID等管理数据(占56字节);用户记录采用链表结构存储实际数据,包含记录头和事务信息;页目录实现记录的二分查找;文件尾含LSN校验值确保数据完整性。不同类型的页(如索引页、系统页)具有特定结构,共同构成InnoDB的存储基础单元。该结构支持B+树索引、MVCC和崩溃恢复等核心功能。
2025-09-23 16:31:17
1497
原创 Mysql杂志(二十一)——Hash索引和二叉搜索树、AVL树
本文比较了哈希索引、二叉搜索树(BST)、AVL树和B+树的数据结构特点及其在数据库中的应用。哈希索引提供O(1)点查询性能但不支持范围查询;BST简单但可能退化为链表;AVL树通过严格平衡保证O(logn)操作,但维护成本高;最后指出B+树因其更矮的高度和高效的范围查询能力,成为数据库索引的首选。各种数据结构各有所长,需根据具体场景选择。
2025-09-22 15:11:22
1144
1
原创 Mysql杂志(二十)——MyISAM索引结构与B树B+树
MyISAM的索引结构既不完全符合B树也不完全符合B+树的特点。其非叶子节点只存储索引键和指针(类似B+树),但叶子节点没有双向链表连接(类似B树),且需要通过数据指针回表查询。相比之下,InnoDB采用标准的B+树结构,叶子节点直接存储数据并形成链表,更适合范围查询。B树适合点查询和文件系统场景,而B+树在数据库OLTP/OLAP场景中优势明显。MyISAM这种混合结构可能是数据库索引演进过程中的过渡形态,最终被更优化的B+树结构所取代。
2025-09-19 16:02:26
1444
原创 Mysql杂志(十九)——InnoDB的索引结构
InnoDB索引采用B+树结构,具有聚簇索引特性。根节点固定不变,随着数据增长,数据页会分裂形成目录页和数据页。目录页包含键值数组和子页指针,通过二分查找和线性对比实现高效检索。索引使用需注意:1)选择高区分度列;2)遵循最左前缀原则;3)避免过度索引;4)不对索引列进行计算;5)正确使用LIKE查询;6)谨慎使用NOT/<>操作符;7)注意OR条件可能导致的索引失效。复合索引创建时需按查询顺序设计字段,优化器会自动调整条件顺序。
2025-09-18 16:57:33
1272
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅