- 博客(305)
- 收藏
- 关注
原创 数据库表介绍
d_program_show_time(节目演出时间表)d_order_ticket_user(购票人订单表)d_program_category(节目类型表)d_ticket_category(节目票档表)d_depth_rule(深度调用限制规则表)d_program_group(节目分组表)d_user_mobile(用户手机表)d_user_email(用户邮箱表)d_refund_bill(退款表)d_api_data(API执行表)d_pay_bill(支付表)d_user(用户表)
2025-07-22 22:19:49
646
原创 Day22
在高并发场景下,为了保证数据库和缓存的一致性,我会把写库操作和缓存更新解耦,用消息队列来做异步更新:先写数据库成功后,发送一条变更消息到消息队列,然后由多线程消费者去消费这条消息,读取最新的数据库值写回缓存,同时配合分布式锁保证同一份数据在同一时刻只会被一个线程更新缓存,避免并发覆盖的问题,这样可以提升吞吐量、减少写库时的阻塞,并且在极端场景下还可以结合延迟双删或定时任务做兜底修正,最终保证缓存和数据库的一致性。一旦检测到丢包,比如收到了 3 个重复 ACK,就触发快重传,立即重发丢失的数据包,不等超时;
2025-07-16 13:20:44
651
原创 Kafka
每个消费者组(Consumer Group)中的消费者都会独立地维护自己的 offset,当消费者从某个 partition 读取消息时,它会记录当前读取到的 offset,这样即使消费者崩溃或重启,它也可以从上次读取的位置继续读取,而不会重复读取或遗漏消息。Replica:副本,为实现备份功能,保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失,且 Kafka 仍然能够继续工作,Kafka 提供了副本机制,一个 topic 的每个分区都有 1 个或多个副本。
2025-07-13 19:50:01
1637
原创 Day21
volatile 关键字能保证变量的 可见性,也就是说,当一个线程修改了 volatile 变量的值,其他线程能立即看到最新值,避免数据不一致的问题。相比 synchronized 或 Lock 是通过加锁来共享同一个变量,ThreadLocal 则是让每个线程有自己独立的变量副本,不需要加锁,是空间换时间的思路。ThreadLocal 可以理解为本地变量,它会在每个线程中创建一个副本,实现线程之间的隔离,避免并发冲突,相当于是用空间换时间的方式来解决线程安全问题。
2025-07-09 20:07:03
799
原创 Day20
集群部署是指将一个系统的服务部署在多台服务器上,这些服务器对外表现为一个整体,通过负载均衡将请求分发到不同的服务器,从而提升系统的并发处理能力和容错能力。如果是使用传统的基于 Session 的认证机制,会遇到问题:Session是保存在服务端的内存或缓存中的,如果用户第一次请求分配到了A服务器并登录,Session存在A上,下一次请求如果被分配到B服务器,B并不知道用户在登录状态,从而导致认证失败。
2025-07-08 12:49:04
730
原创 Day19
JDK1.7中,ConcurrentHashMap 将整个表分为若干段(默认16段),每段维护一部分数据,只有访问同一段的数据才需要竞争锁,从而提高了并发性。JDK1.8中,移除了Segment,结构变成:Node[] + 链表 / 红黑树。改用了 CAS 和 synchronized 组合方式,先用 CAS 尝试插入,如果失败再用 synchronized 锁住某个桶(Node链表或红黑树)进行插入,这样锁的粒度更小,性能更高。总结:因为它在不同版本中采用了不同的并发控制机制。
2025-07-07 21:03:14
632
原创 Day18
Reactor 通过 I/O 多路复用技术,如 epoll,监听客户端连接与数据读写事件。但它也存在短板,无法利用多核 CPU 性能,若业务处理耗时,如对大型集合排序,会阻塞整个进程,导致其他请求响应延迟,仅适用于业务处理快速的场景。Redis 采用 I/O 多路复用技术的原因是:它本身是单线程架构,为了避免在处理客户端请求时因某个连接的阻塞 I/O 操作(如读/写)导致整个线程停顿,Redis 使用多路复用来同时监听多个连接的就绪状态,从而在一个线程内高效地管理大量并发客户端,保证系统高性能和低延迟。
2025-06-10 20:14:37
950
原创 Day17
操作系统的内存管理(Memory Management)是指操作系统对主存(RAM)进行分配、使用、回收和保护的过程。通过地址映射、分段、分页和虚拟内存等机制,为每个进程提供独立、安全且高效的内存使用环境。它将程序使用的逻辑地址转换为物理地址,采用分页方式划分内存以避免碎片,通过页表和 TLB 实现高效映射。虚拟内存允许进程使用超过物理内存的空间,并结合缺页中断与页面置换算法实现按需加载。当内存不足时,系统可将部分内存页换出到磁盘(Swap)。
2025-06-09 14:41:23
871
原创 Day16
在 Java 中,线程池是由 Executor 框架提供支持的,核心接口是 ExecutorService,具体实现类由 ThreadPoolExecutor 提供。固定线程池:创建一个固定大小的线程池,核心线程数和最大线程数都为 nThreads,不会回收线程。适用于任务数量恒定、长期执行,避免线程频繁创建销毁。缓存线程池:线程数不固定,有空闲线程就复用,否则就创建新线程;空闲线程超过 60 秒就回收。适用于执行很多短期异步任务,任务量不确定,适合高并发、瞬时请求。
2025-06-08 13:21:33
702
原创 Day15
CAP 是分布式系统中的一个基本原理,它指出在一个分布式系统中,最多只能同时满足以下三个属性中的两个,三者不可兼得。Consistency(一致性):所有节点在同一时间看到的数据是一致的(等价于单机系统的强一致性)。例如:你写入了一个值,所有节点立刻都能读到这个值。Avaliability(可用性):系统始终保证对客户端的请求返回响应,不管响应是成功或失败,至少能有结果。即使部分节点故障,系统也能继续提供服务。
2025-06-07 22:01:19
678
原创 Day14
DDoS(Distributed Denial of Service,分布式拒绝服务攻击)是一种利用大量分布在全球各地的被攻击者控制的“僵尸网络”(Botnet)发起的攻击。攻击者通过这些大量被感染的设备,向目标服务器或网络持续发送海量请求或流量,耗尽目标的计算资源、带宽或服务能力,导致服务器无法正常响应合法用户的请求,最终造成服务中断或者严重性能下降。相比单点的DoS攻击,DDoS攻击的流量更大、来源更分散,防御更为复杂。
2025-06-06 21:48:28
676
原创 Day13
索引是提高数据库查询效率的一种数据结构。就像书的目录页,可以快速定位到想要查找的内容。在没有索引时,MySQL 只能全表扫描,查询效率低;有了索引后,可以大幅提高 SELECT 查询的速度,尤其是大数据量时。MySQL 的 InnoDB 存储引擎使用的是 B+ 树结构来组织索引数据。B+ 树是一种多路平衡查找树,所有的实际数据都保存在叶子节点,非叶子节点仅存储索引键和指向子节点的指针。相比于 B 树,B+ 树的非叶子节点不存储具体数据,使得单个节点可以容纳更多索引项,从而降低树的高度,提高查询效率。
2025-06-05 21:31:58
1055
原创 Day12
IOC 全称是 Inversion of Control,中文叫做“控制反转”,它是一种设计思想,不特指某个技术或框架。在 Spring中,IOC 的核心含义是:对象的创建、初始化、以及它所依赖的其他对象的注入,不再由我们自己控制,而是交给 Spring 容器负责。Spring 是通过依赖注入(DI)机制来实现控制反转,即:你不需要创建依赖对象,而是通过注入的方式由 Spring 自己提供。注入方式描述说明示例注解或语法构造器注入在创建对象时通过构造方法传入依赖对象(强依赖推荐)
2025-06-04 22:16:46
813
原创 Day11
因为基于 UDP 实现 DNS 能够提供低延迟、简单快速、轻量级的特性,更适合 DNS 这种需要快速响应的域名解析服务。低延迟:UDP 是一种无连接的协议,不需要在数据传输前建立连接,因此可以减少传输时延,适合 DNS 这种需要快速响应的应用场景。简单快速:UDP 相比于 TCP 更简单,没有 TCP 的连接管理和流量控制机制,传输效率更高,适合 DNS 这种快速传输数据的场景。轻量级:UDP 头部较小,占用较少的网络资源,对于小型请求和响应来说更加轻量级,适合 DNS 这种频繁且短小的数据交换。
2025-06-03 23:17:17
683
原创 Day10
Java 中的类加载器过程是指 JVM 在运行期间,将 .class 字节码文件加载到内存中,并转换为可以被虚拟机执行的类对象的过程。加载:把.class文件读进内存,变成 JVM 能识别的 Class 对象。通过类的全限定名(包名 + 类名)找到对应的 .class 文件,把二进制字节流转成 JVM 方法区里的运行时数据结构,并在堆中创建一个代表该类的对象,用来访问方法区中该类的结构信息。链接:验证 + 准备 + 解析验证:检查.class文件是否符合 JVM 要求,确保安全、合法。
2025-06-02 20:05:36
798
原创 Day09
在 Spring 中,Bean 默认是单例模式,即每个 Bean 在整个 Spring 容器中只会被实例化一次,并存储在容器的缓存中。若在定义 Bean 时将 score 属性设置为“prototype”,则每次从容器中获取该 Bean 时,Spring 都会创建一个新的实例。这种模式适用于具有状态的 Bean 或线程不安全的场景。Spring 只帮我们管理单例模式 Bean 的完整生命周期,对于 prototype 的 Bean,Spring 在创建好交给使用者只会,则不会再管理后续的生命周期。
2025-06-01 13:29:38
878
原创 Day08
自增 ID 更快,因为是递增的,插入数据时可以顺序写入 B+ 树的末尾,定位快、写入高效,几乎不会触发页分裂,页的填充率也更高。此外,UUID 占用更多内存和存储空间,导致索引树更高,查询性能下降。因为 InnoDB 的聚簇索引要求数据尽量顺序插入,自增 ID 是单调递增的,写入时总是追加在数据页的尾部,能避免也分裂,提升写入性能。RDB的优点是恢复速度快、文件体积小、适合做全量备份,但其缺点是数据不够实时,一旦 Redis 异常宕机,最后一次快照之后的数据更改将丢失,不适用于对数据完整性要求极高的场景。
2025-05-31 21:40:15
765
原创 Day07
如果在多线程场景中使用它们,需要通过手动加锁,或者使用 Collections.synchronizedXXX() 进行包装,或者干脆选择 ConcurrentHashMap、CopyOnWriteArrayList 等专门为并发设计的集合类。在 Java 中,像 Vector、Hashtable 和 Properties 这些集合类是线程安全的,它们的方法都使用了 synchronized 关键字修饰,能够在多线程环境下保持数据一致性。堆更灵活,能存储更复杂的数据,但管理和性能开销更大。
2025-05-30 13:12:05
763
原创 Day06
在 InnoDB 存储引擎中,如果两条 UPDATE 语句操作的是主键范围不重叠的数据,比如一条更新 id < 10,另一条更新 id > 15,是不会发生阻塞的。此外,InnoDB 还实现了间隙锁、Next-Key Lock、意向锁、自增锁和元数据锁等多种锁机制,用于控制并发和防止幻读,比如间隙锁就会锁住两个索引值之间的范围,防止其他事务插入新记录。一般来说,MySQL 用于持久化存储结构化数据,比如用户信息、订单记录、商品库存这些核心业务数据,数据需要严格的完整性、一致性保障,支持复杂查询和事务操作。
2025-05-29 22:13:09
973
原创 Day05
事务传播行为是指一个事务方法被另一个事务方法调用时,事务如何传播和处理。Spring 事务传播机制就是解决调用链上多个事务之间的关系和边界问题。传播行为含义说明(默认)如果当前没有事务,则新建一个事务;如果已有事务,加入该事务。如果当前有事务,则加入事务;如果没有事务,则以非事务方式执行。必须在一个已有事务中运行;如果当前没有事务,则抛出异常。始终新建一个新事务,如果当前存在事务,则将当前事务挂起。以非事务方式运行,如果当前存在事务,则将当前事务挂起。以非事务方式运行,如果当前存在事务,则抛出异常。
2025-05-28 21:09:58
679
原创 Day04
每个对象有一个 monitor(监视器锁),当线程第一次获取该对象的锁,锁计数器 + 1,如果这个线程再次请求同一个锁(重入),计数器继续 + 1,直到退出 synchronized 块或方法时,计数器依次递减,归0时真正释放锁。notify():只唤醒一个线程,其他线程仍处于等待状态。线程处于 wait() 状态时,会释放对象锁并进入等待队列,底层实际上调用了类似 LockSupport.park() 的方法,使线程进入等待(WAITING)状态,线程此时没有占用CPU资源。
2025-05-27 21:59:25
947
原创 Day02
首先,在消息生产阶段,生产者发送消息后必须等待 RabbitMQ 返回确认(ack),如果出现异常则需要重试,确保消息成功写入队列,避免消息丢失。其次,在消息存储阶段,RabbitMQ 通常以集群方式部署,消息会同步写入多个节点副本,即使某个节点宕机,也能保证数据不丢失,提高系统的高可用性和容错能力。最后在消息消费阶段,消费者在完成消息处理后才发送确认,这样如果消费者异常宕机,消息不会丢失,RabbitMQ 会将未确认的消息重新投递给其他消费者。另外,通过分布式锁防止并发写冲突,也是保障一致性的重要手段。
2025-05-25 22:15:52
907
原创 Java多线程&JUC
多线程是一种程序执行方式,它允许一个程序在同一时间运行多个线程,每个线程可以看作是程序中的一个执行单元。多线程的目的是提高程序的并发性、利用多核CPU的性能、提升执行效率。
2025-05-25 21:01:29
891
原创 Day01
幻读:一个事务中前后两次执行相同条件的查询,结果集的记录条数不一致,因为其他事务插入了符合条件的新数据。它的核心思想是:每个事务在读数据的时候,其实看到的是数据在某个时间点的“快照”,而不是最新的值。快速排序是不稳定的算法,是基于比较的内部排序中性能最好的方法之一,当待排序关键字是随机分布时,平均时间复杂度为O(nlogn),适用于内存足够且速度要求高的场景。MVCC 让事务在读数据时看到的是符合当前事务版本的数据快照,从而避免加锁冲突,实现高并发读操作,是 InnoDB 保证性能和一致性的重要机制。
2025-05-24 15:37:59
911
原创 Day54 验证二叉搜索树
空间复杂度:O(n),其中 n 为二叉树的节点个数。递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,即二叉树的高度。最坏情况下二叉树为一条链,树的高度为 n ,递归最深达到 n 层,故最坏情况下空间复杂度为 O(n)。时间复杂度:O(n),其中 n 为二叉树的节点个数。在递归调用的时候二叉树的每个节点最多被访问一次,因此时间复杂度为 O(n)。时间复杂度:O(n),其中 n 为二叉树的节点个数。空间复杂度:O(n),其中 n 为二叉树的节点个数。
2025-04-20 13:58:48
299
原创 Day53 二叉树的层序遍历
空间复杂度:O(n)(最坏情况下队列存储所有叶子节点)空间复杂度:O(h)(递归栈空间,h为树高)时间复杂度:O(n)时间复杂度:O(n)
2025-04-18 12:49:20
360
原创 GO语言入门
常量是一个简单值的标识符,在程序运行时,不会被修改的量。常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。显式类型定义:隐式类型定义:const (Unknown = 0 // 未知Female = 1 // 女性Male = 2 // 男性常量可以用函数计算表达式的值。const (a = "abc"b = len(a)函数体func:函数由 func 开始声明。
2025-04-14 13:47:05
1717
3
原创 Day50 单词规律
时间复杂度是 O(n),其中 n 是字符串 s 中单词的数量,或者是模式 pattern 的长度。因为我们只遍历了一次字符串和模式。空间复杂度是 O(n),因为我们使用了两个哈希映射来存储字符和单词的映射关系。
2025-03-30 22:03:29
377
原创 Day49 最长连续序列
综合来看,总时间复杂度为 O(n),空间复杂度为 O(n)(存储 HashSet)。构造 HashSet:遍历 nums 存入 HashSet,时间 O(n)。每个元素最多访问两次(一次作为起点,一次在扩展时访问),总时间 O(n)。查找起点 & 计算最长序列:遍历 numSet 一次 O(n)。
2025-03-25 15:20:08
122
原创 Redis实战
数据表介绍:后端的最初功能都是基于Mybatis-Plus搭建的,前端代码后面有空再用Vue写更新。发送验证码:用户在提交手机号后,会校验手机号是否合法,如果不合法,则要求用户重新输入手机号如果手机号合法,后台此时生成对应的验证码,同时将验证码进行保存,然后再通过短信的方式将验证码发送给用户短信验证码登录、注册:用户将验证码和手机号进行输入,后台从session中拿到当前验证码,然后和用户输入的验证码进行校验,如果不一致,则无法通过校验,如果一致,则后台根据手机号查询用户,如果用户不存在,则为用户创建账号信
2025-03-13 15:30:58
786
原创 Day47 环形链表
判断链表是否有环,通常可以使用 快慢指针法,该方法通过两个指针(慢指针和快指针)遍历链表,如果链表中有环,两个指针最终会相遇。如果链表中存在环,快指针最终会追上慢指针。否则,快指针会先到达链表末尾(null),说明链表没有环。时间复杂度:O(n),其中 n 是链表的节点数。快慢指针最多遍历整个链表一次。空间复杂度:O(1),只用了两个额外的指针,空间复杂度是常数。
2025-03-06 16:16:28
166
原创 React
JSX是React的核心内容JSX表示在JS代码中书写HTML结构,是React声明式的体现使用JSX配合嵌入的JS表达式,条件渲染,列表渲染,可以渲染任意的UI结构结果使用className和style的方式给JSX添加样式React完全利用JS的语言自身的能力来编写UI,而不是造轮子增强HTML的功能。(对比VUE)
2025-03-06 14:21:02
1526
1
原创 Day46 反转字符串
时间复杂度: O(n),其中 n 是字符串的长度,因为我们只遍历了一次字符串,并在每次处理时执行常数时间的反转操作。空间复杂度: O(n),用于存储字符数组。
2025-02-26 21:43:54
229
原创 Day45 最长公共前缀
时间复杂度:最坏情况下,每个字符串都需要与前缀进行比较,比较次数为 O(n * m),其中 n 是字符串数组的长度,m 是最长字符串的长度。空间复杂度:O(1)。
2025-02-25 19:17:27
218
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人