- 博客(442)
- 收藏
- 关注
原创 牛客周赛 Round 117 ABCDE 题解
这篇代码合集包含了5个编程竞赛题解。A题通过简单判断输入方案输出对应结果;B题寻找菊花图的中心点;C题计算两种不同排列矩阵的总贡献值;D题通过调整树的连接方式将其转变为链状结构;E题使用BFS寻找马走日的最短路径,并处理多余步数的情况。每个题解都包含了详细的分析思路和对应的Java实现代码,展示了不同算法问题的解决方法和实现技巧。
2025-11-10 09:46:51
130
原创 Java复习事务相关 mysql事务隔离级别 spring事务的传播机制 2025年11月9日
本文系统介绍了MySQL事务隔离级别和Spring事务传播机制。MySQL提供四种隔离级别:读未提交、读已提交(解决脏读)、可重复读(解决不可重复读,InnoDB默认)、可串行化(解决幻读)。Spring事务传播机制定义了多个事务方法相互调用时的处理方式,重点讲解了REQUIRED(默认)和REQUIRES_NEW机制,并通过电商下单和用户注册案例说明如何根据业务需求选择合适的事务传播策略。选择时应考虑业务方法间的依赖关系,判断是否需要事务合并、独立或嵌套执行。
2025-11-09 18:50:02
670
原创 git本地分支创建
本文整理了常用Git命令及其说明,主要包括:仓库初始化(git init)、远程仓库关联(git remote add)、代码暂存与提交(git add/commit)、代码推送(git push)、分支创建与切换(git branch/checkout)等基础操作。同时详细介绍了本地创建并推送新分支到远程仓库的完整流程:先创建分支(git branch),再切换分支(git checkout),最后推送并关联远程分支(git push -u)。这些命令能有效支持团队协作开发,通过分支管理保障主分支稳定性。
2025-11-08 11:46:25
254
原创 maven常用的命令
摘要:本文整理了Maven常用命令,分为6大类:1)基础构建与清理命令(clean/compile/package等);2)依赖管理命令(查看依赖树、分析依赖等);3)生命周期与阶段说明;4)测试相关命令(指定测试类/方法);5)项目信息与辅助命令(查看POM/创建项目);6)其他实用命令(批量修改版本号等)。文中提供了组合命令示例和使用建议,帮助开发者高效完成项目构建、测试和部署工作。
2025-11-08 11:45:42
361
原创 算法与数据结构 线段树模版 Java 求和 求积
本文提供了四种线段树模板实现:1. 基础线段树(求和版):支持区间求和、区间更新和单点更新操作,使用懒加载优化区间更新效率;2. 线段树(求积版):支持区间求积和单点更新操作;3. 线段树(求积取模版):在求积基础上增加模运算功能,适用于大数运算场景。所有实现均采用递归方式构建树结构,支持区间查询和单点更新,通过4*n的数组大小确保存储空间足够。模板设计灵活,核心操作如合并函数可根据需求修改为求和、求积或其他操作。
2025-11-08 11:40:13
224
原创 牛客周赛 Round 114 Java题解
本文包含六个编程问题的解答方案。A题通过枚举实现数字查找;B题暴力求解满足条件的好字符串子串;C题分析字符串交换的最少操作次数;D题使用动态规划解决数组选数问题;E题通过构造特定条件数组满足要求;F题采用构造法生成符合特定规则的数字。各题均提供完整的Java实现代码,涵盖输入处理、算法逻辑和结果输出。
2025-11-08 11:38:39
305
原创 Java复习 多线程基础篇 2025年11月7日
本文介绍了线程生命周期中的5种状态(新建、就绪、运行、阻塞、终止)及其转换方式。详细解析了线程常用方法(start/run, wait/sleep, notify等)的特点与区别,并比较了三种创建线程的方式(继承Thread、实现Runnable、Callable+FutureTask)。重点讲解了线程池的概念、核心参数(线程数、存活时间等)和执行流程,说明其通过复用线程提高效率的原理。文章为理解线程管理和线程池实现提供了系统性的技术参考。
2025-11-08 11:37:44
314
原创 结合源码分析MyBatis的缓存机制
本文分析了MyBatis多级缓存机制。一级缓存是SqlSession级别的本地缓存,基于HashMap实现,生命周期与SqlSession一致;二级缓存可在多个SqlSession间共享,通过CachingExecutor实现。配置时需在settings中开启相关选项,一级缓存容易导致脏数据,二级缓存在多表查询时也存在数据一致性问题,特别是在分布式环境下更推荐使用专门的分布式缓存方案。
2025-10-31 18:31:19
299
原创 Spring Bean的生命周期 第二次思考
本文详细解析了Spring框架中Bean的生命周期全过程,主要包括七个关键步骤:1)加载配置源并注册为BeanDefinition;2)实例化Bean并填充属性;3)依赖注入和循环依赖处理;4)初始化前处理(Aware接口和BeanPostProcessor增强);5)执行初始化方法(@PostConstruct和InitializingBean);6)初始化后处理(如AOP代理创建);7)销毁阶段执行销毁逻辑。每个阶段都通过特定接口或注解实现,完整展现了Spring容器管理Bean的全过程。
2025-10-27 20:37:00
623
原创 Java面试八股 CAP理论详解
CAP理论指出分布式系统无法同时满足一致性(C)、可用性(A)和分区容错性(P)三个特性,必须做出取舍。CP系统优先保证数据一致性,如银行交易、医疗系统;AP系统则侧重高可用性,如社交推送、电商列表。实际应用中,应根据业务需求明确优先级:金融等强一致性场景选择CP,互联网高并发场景选择AP。通过决策流程图可帮助选型,关键是要区分数据是否允许延迟、能否接受服务不可用等核心矛盾。理论指导我们合理选择中间件,如MySQL(CP)、Redis(AP)等,避免技术滥用。
2025-10-20 21:41:22
1012
原创 面试八股 快速讲解 集合类中的 fail-fast和fail-safe
摘要: Fail-fast机制在集合操作中会立即检测并发修改(如ArrayList通过比较expectedModCount和modCount),不一致则抛出异常。而Fail-safe机制(如CopyOnWriteArrayList)通过复制副本实现安全遍历,写操作加锁更新数据,但读操作可能读到旧数据,实现最终一致性而非强一致性。示例展示了两种机制的应用差异及并发场景下的处理方式。
2025-10-20 21:31:05
287
原创 上传文件相关业务,采用策略模式+模版方法模式进行动态解耦
本文介绍了一个基于策略模式的文件上传系统实现。通过策略上下文(StrategyContext)管理不同上传策略,核心采用模板方法设计模式,定义UploadStrategy接口和AbstractUploadStrategyImpl抽象类。抽象类实现了通用的uploadFile方法流程(包括MD5计算、文件存在检查等),而具体策略(如CosUploadStrategyImpl)只需实现exists、upload和getFileAccessUrl三个抽象方法。系统通过配置文件动态加载策略,支持多种存储服务扩展,如
2025-10-14 19:36:29
314
原创 Java复习 2025年10月9日 垃圾回收器 Io流 异常 钩子方法相关
本文摘要:介绍了Java编程中的几个核心概念,包括垃圾回收机制、IO流操作和异常处理。垃圾回收器(GC)会自动回收不可达对象的内存,内存泄漏则因对象被不当引用导致。IO流部分重点解析了BufferedReader的高效读取机制,它通过缓冲技术减少底层资源访问。异常分为受检和非受检两类,是程序运行时的可捕获错误。最后通过HttpServlet示例解释了模板方法模式中的钩子方法概念,展示了父类固定流程调用子类重写方法的实现方式。
2025-10-09 16:27:07
366
原创 2025最新centos7安装mysql8 相关 服务器配置 纯命令行操作 保姆级教程
本文介绍了在Linux系统下使用yum安装和配置MySQL数据库的全过程,包括:1)通过yum安装MySQL服务器;2)创建systemd服务文件;3)配置my.cnf文件;4)防火墙开放3306端口;5)设置环境变量;6)服务管理命令;7)查看MySQL日志。重点涵盖了基于目录配置、权限设置、防火墙规则和服务启动等关键步骤,提供了完整的MySQL服务部署方案,适合需要快速搭建MySQL环境的用户参考。
2025-09-27 21:56:08
425
原创 毕业设计 将博客文章数据从mysql放到mongodb里面 设想 (完)
文章摘要: 本文探讨了MySQL与MongoDB混合使用的解决方案。针对MySQL强关联性问题,提出了嵌入式文档、引用式及混合方案三种处理方式。通过工厂模式实现DAO层动态切换,配置驱动选择MySQL或MongoDB服务。采用继承方式实现无侵入式修改,保持原有Service逻辑。详细介绍了MongoDB查询(Criteria/Query类)和更新(Update类)的实现方法,包括条件构建、分页处理和字段更新等核心操作。最后解析了三者的协作关系:Criteria定义条件,Query封装查询,Update描述修
2025-09-27 21:51:30
1045
原创 linux安装hbase(完)
本文介绍了在CentOS7环境下安装和配置HBase的步骤。主要内容包括:使用yum下载HBase安装包并解压到指定目录;配置环境变量和网络服务(hbase-site.sh);安装JDK并配置hbase-env.sh文件;说明HBase启动依赖JDK和Zookeeper,单机环境可使用自带Zookeeper;通过软链接方式解决Java路径问题;最后给出启动HBase服务和进入hbase shell的方法。文章提供了完整的安装配置流程,特别说明了使用yum安装时的路径处理技巧。
2025-09-23 20:14:33
293
原创 MVCC 多版本并发控制 详解
MVCC(多版本并发控制)是数据库实现高并发访问的核心机制,通过版本链、undolog和ReadView三个组件协同工作。隐藏字段记录事务ID和回滚指针,undolog保存历史版本形成版本链,ReadView根据事务隔离级别决定数据可见性。MVCC实现读写不冲突:读操作访问历史版本无需加锁,写操作仅修改当前版本,大幅提升并发性能。不同隔离级别通过调整ReadView生成时机实现不同效果,RC级别每次查询生成新视图,RR级别复用首次视图保证可重复读。MVCC需配合行锁解决写冲突,并定期清理无用历史版本。
2025-07-21 21:51:33
969
原创 AQS 抽象队列同步器 资源竞争-排队等待
AQS(AbstractQueuedSynchronizer)是Java并发包的核心框架,为同步工具提供基础实现。它通过volatile int state表示资源状态,结合CLH等待队列实现线程排队机制。AQS支持两种工作模式:独占模式(如ReentrantLock)和共享模式(如Semaphore)。采用模板方法模式,由子类实现tryAcquire/tryRelease等钩子方法定义具体同步逻辑,而AQS负责排队、阻塞、唤醒等通用流程。基于AQS实现了ReentrantLock、CountDownLat
2025-07-21 21:49:45
989
原创 事务的传播行为,分别在spring和mysql中讲解
本文对比分析了Spring框架与MySQL数据库中的事务传播机制。Spring在应用层定义了7种传播行为(如REQUIRED、REQUIRES_NEW等),通过AOP代理控制事务交互;MySQL则通过存储引擎(如InnoDB)提供底层事务支持,包括保存点机制和自动提交特性。两者协作实现复杂事务场景:Spring的传播行为规则依赖MySQL的基础事务能力,如NESTED对应保存点机制,REQUIRES_NEW依赖事务独立性。这种分层设计使开发者能在应用层灵活控制事务边界,同时确保数据库层的原子性和隔离性。
2025-07-20 17:07:49
1062
1
原创 电商领域企业级应用后端开发 (Java) 就业前景深度分析报告 (2025-2030)
电商行业作为数字经济的核心组成部分,正经历从增量扩张向存量深耕的战略转型。2025 年中国网络零售额已突破 18 万亿元,同比增长 9.3%,标志着电商行业进入精细化运营阶段。精耕细作新周期:电商行业已全面进入 "争存量 + 夺增量" 的新阶段,消费新趋势、技术及商业模式创新,以及全球化扩张成为行业增长的主要驱动力。技术驱动变革:人工智能、区块链等技术的应用正推动电商行业向价格透明化和物流智能化方向发展。预计到 2027 年,具备动态定价分析能力的企业占比将提升至 65%。跨境电商持续扩张。
2025-06-24 12:19:28
3138
原创 实战 使用分布式锁注解来确保用户注册邀请时的原子性、可见性、有序性
摘要:本文介绍了基于Redisson实现的分布式锁解决方案,采用注解方式定义锁场景。通过AOP切面拦截被@DistributeLock标记的方法,支持从注解或SpEL表达式获取锁key,并提供灵活的超时与等待配置。应用场景包括注册防重(锁手机号)和邀请积分防错(锁邀请人ID),其中注册通过注解实现,邀请积分则需手动加锁。系统采用双保险机制,注册锁与邀请锁分别控制不同资源,确保并发场景下的数据一致性。
2025-06-23 15:32:08
239
原创 微服务架构中用aop和facade注解实现对rpc结果的统一封装和日志打印
FacadeAspect是一个基于SpringAOP的切面处理类,主要用于增强标注@Facade注解的方法。它通过环绕通知实现三大核心功能:1) 参数校验机制,对所有方法参数进行JSR-303规范校验;2) 统一的日志记录系统,完整记录方法执行过程包括耗时、结果和异常;3) 异常处理流程,将业务/系统异常转换为标准响应格式。该切面还实现了响应结果自动补全功能,确保返回BaseResponse类型的统一性。关键技术包括AOP切面、反射技术和性能监控,适用于RPC服务和API接口,有效提升了代码健壮性、可维护性
2025-06-23 15:04:17
888
原创 计算机网络期末 物理层
本文摘要梳理了数据通信基础的关键知识点,重点包括:传输介质(有线/无线)、基带传输的数字编码原理(曼彻斯特编码特性)、频带传输的调制技术,以及多路复用和物理层设备。内容涵盖介质类型(同轴电缆、光纤、微波等)、编码方法(电平变化规则)、调制解调概念及典型例题解析,适合快速掌握通信技术核心内容。全文层次清晰,突出基础概念与实际应用(约120字)
2025-06-22 17:50:31
342
原创 计算机网络期末 网络基础概述
《计算机网络基础概念》摘要: 计算机网络是通过通信设备和线路连接多台计算机实现资源共享的技术系统,经历了面向终端、分组交换、标准化和互联网四个发展阶段。网络按范围分为PAN/LAN/MAN/WAN,拓扑结构包括星型、环型等。OSI七层模型(物理层至应用层)与TCP/IP四层模型(网络接口至应用层)是核心参考架构。关键性能指标包含带宽、时延等,其中时延由传输、传播、处理及排队时延组成。理解这些基础概念是掌握网络技术的首要前提。
2025-06-22 12:30:51
236
原创 redis分布式锁 Redisson在电商平台开发中的实际应用
摘要:本文系统介绍了Redis分布式锁的实现方式与应用场景,包括SETNX命令、SET参数、Lua脚本和RedLock算法等基础实现,重点分析了Redisson的可重入锁特性及内部机制。针对电商典型场景,详细阐述了库存超卖控制、订单防重复提交和促销活动限流三个案例的解决方案,包含锁粒度控制、原子性保证等关键实现细节。最后总结了分布式锁的最佳实践,强调合理设置超时时间、异常处理机制和性能监控的重要性。全文提供了从基础原理到实战落地的完整技术方案。
2025-06-21 21:07:39
520
原创 分布式锁 不同的拒绝策略 应用场景 业务上的思考
文章摘要:分布式锁场景下未获取锁的用户处理策略包括自旋等待(适合短事务)、阻塞等待(适合长事务)、立即失败(适合高并发)和异步处理(适合削峰)。替代Redis锁的方案有数据库乐观锁、ZooKeeper锁、本地锁和分布式事务。面试应答应结合项目场景说明选择逻辑,强调技术权衡,如游戏账号查询采用自旋等待+超时策略,秒杀场景用立即失败保护系统。(149字)
2025-06-21 19:11:46
1275
原创 2025年6月19日泛微软件北京 26届校园招聘 一面
摘要:本文记录了参加泛微软件北方大区校园招聘会的经历。虽然已有暑期实习,但仍参加线下宣讲会。招聘会现场人气火爆,面试环节涉及多个技术问题:MySQL事务与Spring事务区别、事务隔离级别、数据库调优、Elasticsearch实现原理(倒排索引)及与MySQL数据一致性方案(消息队列异步双写/Canal监听binlog)。最后了解到该公司主要从事全栈客制化开发,技术栈与学校所学相近。整个流程展现了企业招聘的技术考察重点和实际开发需求。
2025-06-19 12:45:09
653
原创 电商实战:秒杀场景方案2 :基于hint实现库存热点扣减
本文介绍了基于InventoryHint的库存扣减方案。通过SQL语句中的hint关键字(如COMMIT_ON_SUCCESS、ROLLBACK_ON_FAIL等),可以优化MySQL对热点数据的更新处理。该方案将update操作分组执行,通过减少行锁等待、B+树索引遍历和事务提交次数,提升库存扣减、退还和占用的操作效率。相比Redis+RocketMQ的削峰方案,该方案直接利用MySQL内核优化机制,简化了系统架构。
2025-06-16 21:52:33
268
原创 电商实战:秒杀下单场景方案1 :Redis+MQ实现
本文介绍了一种基于Redis和RocketMQ的秒杀系统设计方案。系统通过Redis的Lua脚本保证库存有序扣减,利用其高并发特性过滤部分请求。剩余请求通过RocketMQ事务消息进行削峰处理,确保消息可靠投递。方案采用事务消息反查机制防止消息丢失,并详细阐述了消费失败时的重试策略,包括设置最大重试次数、死信队列处理、幂等性设计以及告警监控机制。整个方案有效解决了秒杀场景下的高并发库存扣减和系统稳定性问题。
2025-06-16 21:50:16
1376
1
原创 mysql 字段的Null和‘‘有什么区别
MySQL不建议使用NULL作为默认值的原因主要有四方面:1)存储效率上,NULL需要额外的标志位且对动态类型造成冗余;2)查询性能上,影响索引效率并增加过滤复杂度;3)逻辑处理上,NULL比较存在陷阱且影响聚合函数结果;4)数据完整性上,可能导致业务歧义和外键问题。适合使用NULL的场景包括未知数据、三值逻辑需求等;而空字符串更适合字符串类型、需参与运算等场景。最佳实践建议优先设置NOT NULL加默认值,仅在必要时允许NULL,同时应在应用层统一处理空值逻辑。合理选择空值表示方式能提升存储效率、查询性能
2025-06-16 18:30:22
892
原创 蓝桥杯国赛训练 day4
本文包含四个Java编程问题的解决方案:1)统计数组元素超过当前最大值的次数;2)优化两种分配方案的总收益;3)寻找排序数组中最小窗口差值;4)计算字符串中各字符频次的最大差值。所有问题都采用高效算法实现,包括遍历统计、排序优化和滑动窗口等技巧。通过标准输入处理数据,时间复杂度控制在合理范围内,适合编程竞赛场景。代码结构清晰,展示了Java集合框架和数学工具类的典型应用。
2025-06-12 19:16:20
324
原创 蓝桥杯国赛训练 day3
本文介绍了多个Java编程问题的解法,包括: 01串计数:通过多层循环生成所有可能的24位01串,并筛选满足连续5位不超过3个1的字符串。 互质数查找:遍历数字查找与2024互质的第2024个数,使用最大公约数判断互质关系。 阶乘求值:计算大数阶乘并取模,使用BigInteger处理大数运算。 密文搜索:通过滑动窗口统计字符串中8位子串与给定密文的匹配次数。 蓝桥字符统计:统计字符串中"l"、"a"、"n"的组合情况,计算特定模式的出现次数。 穿越
2025-06-10 18:40:09
380
原创 电商实践 基于rocketmq实现订单取消后的分布式事务回滚 代码实现
目录前言图流程自己的思考Java支持简单的示例电商订单支付后消息发送实现 秒杀场景 redis扣减后持久化到数据库前言在微服务架构中,我们的服务是独立部署,一些复杂的业务操作往往涉及很多服务,而这时我们就遇到了分布式事务的问题,我们要保证这些独立部署的服务中的操作要么全部成功要么全部失败所以我采用的RocketMQ实现了分布式事务,也是进行了学习图流程我们生产者控制着本地事务首先会发送一个半事务消息给mq然后mq接收成功后返回一个ac
2025-06-09 21:29:17
1115
原创 滴滴 服务端 面经
一、缓存与数据库的使用场景及性能差异1. 缓存的适用场景高频读、低频写场景:如商品详情页、用户信息等读多写少的数据,减少数据库压力。实时性要求不高的数据:如首页推荐列表、统计数据(非实时更新),允许短时间内数据不一致。高并发场景下的性能优化:通过缓存抗住流量峰值,避免数据库直接被击穿(如秒杀活动中的库存查询)。2. 数据库的适用场景数据持久化与强一致性场景:如用户交易记录、订单状态变更,需保证数据不丢失且事务完整。复杂查询与业务逻辑:涉及多表关联、聚合统计(如SQL的JOIN、GROUP BY
2025-06-07 17:00:59
1273
原创 企业级开发 如何设计数据库和缓存来实现微信朋友圈好友可见
本文分析了微信朋友圈"好友可见"功能的实现流程,提出了基于Redis的高效存储方案。核心设计包括:1) 使用Redis Set存储好友关系;2) 朋友圈内容用Hash存储并设置可见性字段;3) SortedSet按时间索引朋友圈ID。发布流程涉及内容存储和可见性标记,查询流程通过好友遍历和权限校验实现。方案采用Java实现,包含用户模型、Redis工具类、好友关系服务和朋友圈服务等模块,支持发布、分页查询和可见性控制功能。文中还提出了批量操作、本地缓存等优化建议。该设计充分利用Redis
2025-06-07 16:06:03
638
原创 DDD架构实战 领域层 事件驱动
摘要:本文展示了DDD领域驱动设计中事件驱动的实现方案,通过领域事件实现业务逻辑解耦。核心方案包括:1)定义DomainEvent接口和具体事件类;2)DomainEventBus单例事件总线负责事件分发;3)聚合根管理事件发布;4)业务服务通过订阅模式处理事件。示例演示了订单支付触发库存扣减的场景,体现了松耦合优势。该方案具有解耦业务、增强扩展性、保障最终一致性等特点,实际应用中可结合事件持久化、重试机制和消息队列等进一步优化。
2025-06-06 18:54:21
752
原创 DDD架构实战 充血模型 电商订单
充血模型是一种领域驱动设计(DDD)的核心模式,强调领域对象既包含数据属性又包含业务逻辑方法。它将业务规则集中封装在领域层,使模型更贴近真实业务场景。充血模型具有强封装性、支持复杂业务逻辑、便于领域知识传递等特点,相比贫血模型在逻辑一致性、可维护性、健壮性等方面更具优势。实现要点包括明确实体与值对象划分、合理使用领域服务和事件、采用仓储模式等。尽管存在建模门槛高、初期成本高等挑战,但在金融、电商等复杂业务系统中具有显著价值。该模型通过"数据与行为绑定"的设计,将业务逻辑回归到领域本身,是
2025-06-06 18:53:08
1558
原创 蓝桥杯国赛训练 day2 Java大学B组
本文展示了四个Java算法竞赛题的解决方案:1)"抓猪拿国"计算1到16的累加;2)"社区服务"处理二进制字符串,计算每个0到最近1的距离;3)"分考场"用回溯法分配不冲突的学生到最少考场;4)"拉马车"模拟双人卡牌对战游戏。代码均采用模块化设计,包含输入处理和核心算法逻辑,展现了典型竞赛编程技巧和数据结构应用。所有方案通过GitHub开源共享,体现了算法竞赛的解题思路和实现方法。
2025-06-06 12:57:34
225
原创 LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
摘要:该文档描述了基于Lua脚本和Redis实现的库存预扣减方案,通过原子性操作确保秒杀场景的高效性。Lua脚本包含库存检查、扣减和流水记录功能,其中流水记录采用Redis哈希结构存储操作日志,包含操作前后库存值、时间戳等信息。流水记录主要用于实现幂等操作和后续对账,确保Redis与数据库的一致性。流水记录会在完成对账或商品下架24小时后删除。整个方案通过原子性扣减和异步持久化机制,有效解决了高并发场景下的库存管理问题。
2025-06-06 00:07:24
813
原创 自定义注解facade 实现切面 进行日志记录和参数校验
该摘要描述了基于AOP的日志拦截方案。通过在方法上添加@Facade注解,FacadeAspect切面会自动拦截标记方法,提供以下功能:1) 统一参数校验;2) 异常捕获处理;3) 详细日志记录(包括方法名、参数、耗时和执行结果);4) 自动封装响应结果。该方案增强了代码健壮性,简化了日志管理,只需添加注解即可实现方法级监控,支持业务异常和系统异常的统一处理。
2025-06-06 00:06:42
352
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅