- 博客(178)
- 收藏
- 关注
原创 秒杀场景:应改用预扣库存+异步队列方案
该方案是电商秒杀系统的标准实践,能支撑百万级 QPS 的瞬时流量,同时通过最终一致性保证数据可靠。:所有请求必须串行竞争同一把锁(例如热门商品ID对应的锁),导致大量线程阻塞。:允许短暂时间内 Redis 与数据库库存不一致,但通过异步处理最终同步。:网关层缓存库存状态(如剩余库存量),快速拦截无效请求。:业务逻辑耗时越长,锁占用时间越久,系统吞吐量越低。:定期核对 Redis 预扣库存与数据库实际库存。:库存不足时立即返回,减少无效请求进入后续流程。:将单个商品库存拆分为多个分片,分散热点。
2025-03-13 17:52:22
591
原创 MySQL的buffer pool的缓存中,修改语句在执行时,是先更新buffer pool,还是先更新数据库
直接写磁盘(随机 I/O)速度极慢,而修改内存(Buffer Pool)是纳秒级操作,通过异步刷盘将随机写转换为顺序写(Redo Log),极大提升吞吐量。:Redo Log 是顺序追加写入,即使脏页未刷盘,只要 Redo Log 落盘,事务的持久性(Durability)就能通过 Redo Log 恢复来保证。:解决“部分写失效”(Partial Page Write)问题,确保数据页写入磁盘的原子性。如果数据页不在 Buffer Pool 中,会先从磁盘加载到内存,再进行修改。
2025-03-11 14:30:37
479
原创 MySQL查询慢的原因
其次是应用端连接数过小,由于MySQL 和应用的连接是 tcp 长连接,连接比较耗时,因此一般会在应用端建立一个连接池,用来存放长连接,sql 语句查询时,先取出连接使用,用完再将连接放回去。首先需要了解mysql 的查询流程,以我们的 Java 代码为例,Java 应用会带着账号密码尝试和 MySQL 建立网络连接,MySQL 的连接管理模块会对该连接进行管理,连接完成之后,Java 应用会对 MySQL数据库发送 sql 语句,MySQL 收到查询语句后,会在。现在最常用的是innodb 存储引擎。
2025-03-11 10:08:21
178
原创 Cache-Aside + 延迟双删 + 异步重试 + Binlog监听
若强一致性要求极高(如金融交易),需牺牲性能,采用同步写(如Write-Through)+ 分布式事务。例如:线程A更新DB后,线程B可能在更新期间读取旧数据并写入缓存,延迟双删可清除残留旧数据。:通过消息队列和Binlog监听,将缓存清理操作与主流程解耦,提升系统健壮性。将变更事件(如表名、主键ID、操作类型)发送至Kafka,保证事件不丢失。缓存数据携带版本号(或时间戳),写入时校验版本,防止旧数据覆盖新数据。:确保删除操作事件100%投递到MQ(如Kafka的ACK机制)。
2025-03-11 09:27:42
753
原创 Nacos高频面试题10个
通过命名空间(Namespace)和分组(Group)管理不同环境(如dev/test/prod)的配置。:客户端默认每5秒发送心跳包,若15秒未收到响应则标记为不健康,30秒未响应则从服务列表移除。:通过心跳机制和主动探测(如HTTP/TCP检查)监控实例健康状态,自动剔除异常实例。:用于服务发现场景,优先保证高可用性(AP),通过异步复制实现最终一致性。:为不同实例设置流量权重(如新版本10%,旧版本90%),逐步切换流量。:服务实例可动态注册到Nacos,消费者通过服务名发现可用实例。
2025-03-06 18:26:34
940
原创 多线程高频面试题15个
进程间内存隔离,线程共享进程的内存(堆、方法区),但每个线程有独立的栈。场景:线程1读取值A,线程2将A→B→A,线程1再次比较仍认为值未变。:一次性使用,等待多个任务完成(如主线程等待子线程初始化)。:可重复使用,多个线程相互等待到达屏障(如多阶段任务)。JVM 在所有非守护线程退出后立即终止,不等待守护线程。:控制同时访问资源的线程数量(如数据库连接池)。:线程创建工厂(可定制线程名称、优先级等)。:最大线程数(核心线程 + 非核心线程)。为其他线程提供服务(如垃圾回收线程)。
2025-03-06 18:19:38
687
原创 Redis高频面试题10个
结合 RDB 和 AOF,重启时先加载 RDB 快照,再重放 AOF 增量命令。事务中的命令按顺序执行,但不保证原子性(单条命令失败不影响后续执行)。数据持久化:Redis 支持数据落盘,Memcached 纯内存。主节点(Master)写,从节点(Slave)读,支持数据同步。将多个命令打包发送,减少网络往返时间(RTT),提升吞吐量。基于内存的键值数据库,支持持久化(RDB/AOF)。数据分片(16384 个哈希槽),支持水平扩展。主节点关闭 RDB/AOF,从节点开启 AOF。
2025-03-06 18:10:30
977
原创 Redis 缓存穿透、击穿、雪崩的 出现场景 与 解决方案
使用 Redis 集群(Cluster)或哨兵模式(Sentinel)避免单点故障。本地缓存(如 Caffeine) + Redis 缓存,降低 Redis 压力。通过合理设计缓存策略,可显著提升系统在高并发场景下的稳定性和性能。当数据库压力过大时,启用熔断机制(如返回默认值、限流)。(如非法ID),导致请求绕过缓存直接击穿到数据库。对极热点数据不设置过期时间,通过异步线程定期更新。批量缓存设置相同过期时间(如每日零点统一过期)。缓存不设置物理过期时间,但存储逻辑过期字段。明星爆款商品详情页缓存过期。
2025-03-05 18:32:11
575
原创 Redis 主从复制、哨兵与集群的关系及工作原理详解
在分片(Sharding)基础上集成主从复制和自动故障转移(分布式+高可用)。集群中的每个分片(主节点)可配置多个从节点,形成“主从+集群”架构。:从节点(Slave)复制主节点(Master)数据,实现备份。从节点首次连接主节点时,主节点生成 RDB 快照发送给从节点。领导者哨兵从从节点中选出新主节点(基于优先级、复制偏移量等)。:主节点处理写请求,从节点处理读请求,提升读吞吐量。通知其他从节点复制新主节点,并更新客户端连接。:主节点宕机时,选举新主节点并通知客户端。
2025-03-05 15:54:27
698
原创 Redis 各数据类型使用场景详解
高并发下对同一数值进行增减操作时,需保证原子性,避免竞态条件导致数据不一致。哈希表将对象字段存储为单键下的多个字段,减少键数量,支持按字段读写。:Redis 的原子操作确保增减操作的线程安全,无需额外锁机制。动态需按时间倒序展示,且需限制列表长度(如只保留最新100条)。每日签到状态只需记录是否签到(0/1),使用字符串浪费内存。直接计算交集,复杂度为 O(N*M),但内存中操作极快。位图每个位表示一天,每月31天仅需4字节,内存占用极低。多生产者/消费者场景下,需保证消息的顺序性和可靠性。
2025-03-05 14:47:34
780
原创 Redis 基本数据类型总结及使用场景
最简单的键值对,支持文本、整数、浮点数或二进制数据(最大 512MB)。:双向链表,支持头部(Left)和尾部(Right)操作,元素可重复。:元素唯一,每个元素关联一个分数(Score),按分数排序。:统计 UV(独立访客数),误差率约 0.81%。:用户签到记录(每天对应一个位)、活跃用户统计。:分布式日志、事件溯源(类似 Kafka)。:键值对集合,适合存储对象(如用户信息)。:基数统计(估算集合中不重复元素的数量)。:无序且唯一的元素集合,支持交并差运算。:基于字符串的位操作,支持按位存取。
2025-03-05 11:11:26
976
原创 MQ五个作用点以及应用场景
通过异步化,主流程耗时从同步调用的 1 秒(发送短信)降低到 10 毫秒(仅发送消息)。:将突发请求写入 MQ,后端服务按自身处理能力匀速消费(如每秒处理 1000 个请求)。:先发送“半消息”到 MQ,执行本地事务(如扣款),事务成功则提交消息,失败则回滚。:生产者将消息发送到 MQ 后立即返回成功,消费者异步消费消息(如发送短信)。:MQ 堆积消息(如积压 10 万条),服务逐步消费,防止数据库被打满。:订单系统发布消息到 MQ,物流系统订阅消息,双方无需感知彼此的存在。
2025-02-28 10:30:36
371
原创 IDEA启动时,电脑非常的卡
JVM在运行时会回收新生代和老年代的垃圾,新生代无法回收的对象,比如:回收15次都没有回收的、对象很大,超过新生代的50%,就会将这些对象放到老年代,陆陆续续的老年代装满了的话,就会对老年代的对象进行回收,回收的时候就会触发stop the word,就会将所有的资源都拿去回收老年代的对象,多以就很卡,因此,我们调整IDEA的内存大小,就是增加新生代和老年代的内存大小,这样做的目的就是减少垃圾回收。把启动内存调大一点就行了,反正要超过你平时使用IDEA时使用到的内存大小就行。
2024-03-13 16:39:25
671
原创 RabbitMQ-消息延迟
当生产者将消息发送到exchange1,然后交换机将消息路由到队列queue1,但是队列queue1没有消费者,所以当该队列里面的值过期时,就会将消息发送到死信交换机exchange2,进而到达死信队列,最后被消费。从而达到了延迟消息的目的。一个队列接收到的消息有过期时间,消息过期之后,如果配置有死信队列,消息就会进去死信队列。DelayExchange的本质还是官方的三种交换机,只是添加了。因此使用时只需要声明一个交换机,交换机的类型可以是任意类型,然后。
2024-01-21 09:23:00
860
1
原创 如何保证支付服务和交易服务之间订单状态的一致性?
2、其次,为了保证消息的可靠性,采用了生产者确认、消费者确认、消费者重试的机制等策略,确保了消息投递和处理的可靠性。同时开启消息的持久化,避免因为MQ宕机导致消息丢失。1、首先,支付服务在完成订单支付以后,会通过MQ给订单服务发送一个消息,让订单服务完成订单状态的同步。3、最后,业务做了幂等性判断,避免因为MQ的重复消费导致订单状态异常。
2024-01-20 18:41:55
1114
原创 RabbitMQ-业务的幂等性
消费者拿到id之后,保存到数据库,后续消费时,需要查数据库进行比较,因此这种方案的缺点就是有业务的入侵,对性有一定的影响。
2024-01-20 18:35:34
960
1
原创 RabbitMQ-消费者确认机制
消息失败之后会重新入队,然后再次异常,再次入队,无限循环,这会导致mq消息处理飙升,带来不必要的压力。为了缓解这种压力,利用Spring的retry机制,在消费者出现异常的情况下,利用本地重试,重试次数用完之后,再进行消息的投递或者消息的拒绝。
2024-01-20 17:57:14
1446
原创 RabbitMQ-数据持久化
在控制台中,这个delivery_ mode 的值为2时,就表示这个消息是持久化的。手动发消息的时候,可以选择这个值,可以看到他的枚举。SpringAMQP调用时是默认持久化的。
2024-01-20 16:06:20
1102
1
原创 RabbitMQ-生产者可靠性
这种超时重连的方式是阻塞式的,后面的代码没办法执行,如果说业务要求比较严格,则需要禁止使用;如果必要使用的情况下,合理设置重连时间。
2024-01-20 08:08:08
1658
原创 插入排序-insertSort
具体过程是,先将标记元素的值存储起来,然后用标记元素的值和有序数组的最后一个元素比较,如果有序数组的值大于标记数组,则需要将有序数组的比较值赋值到标记元素的位置,随后继续比较有序数组的其他值,当有序数组的值没有了,或者遇到一个值标记值小,那么此时就需要停下来了,因为已经找到了标记值的位置,此时只需要将标记元素的值放到此处即可。与冒泡排序和插入排序一样,也是两个元素比较;时间复杂度为O(N^2),但是相比冒泡排序和选择排序,速度更快。
2024-01-18 19:46:16
511
原创 选择排序-SelectSort
从数组的最左边开始,将数组的第一个元素记录到临时变量中,然后开始循环,循环的目的是找出数组中最小的值,然后将它赋值给临时变量,并且记录这个最小值的下标,一轮循环完毕后,比较最小值的下标和最外层循环的起始下标是否相等,如果不相等,起始下标对应的值和最小值进行交换,得到的数组中,最左边的值就为最小值。两层循环,外层循环是控制循环的次数,也就是比较元素的个数,内层循环是比较两个元素的大小,因此,时间复杂度为O(N^2).
2024-01-18 09:09:54
401
原创 冒泡排序-BubbleSort
从数组的左边开始,比较两个元素的大小,当左边大于右边时,更换左右元素位置,否则不改变;接着向右移动一步,比较第二个元素和第三个元素的大小,重复上述操作,直到最后一个元素,此时,最大的元素就已经移动到了最右边;然后进行下一轮比较,但是下一轮比较时,不需要比较最后一个元素了。
2024-01-18 08:40:52
662
原创 Spring声明式事务失效原因总结
例如:service层的类上面没有加@Service注解,导致这个Bean没有被Spring管理,那么注解也是会失效的。解决办法:将B()方法写到一个新的类里面,交给Spring管理,然后A方法使用外部调用的方式调用B方法。例如:MySQL中 ,MyISAM 引擎是不支持事务,要支持事务都会使用 InnoDB引擎。例如:类中有方法A(),方法B(),A调用了B,B方法上使用了事务注解,此时事务会失效。事务注解修饰的方法不是公共的,事务也会失效。如果业务代码里面的异常被捕获,事务也会失效。
2024-01-16 10:37:32
684
原创 Spring-AOP详解
当需要为多个不具有继承关系的对象引入一个公共的行为,例如:日志、安全检测等,起初我们只有在每个对象里面引用这些公共的行为,但是这样做会导致程序出现大量的重复代码,不便于维护。//参数类Class<?//操作类型@Aspect@Component@Resource/*** 定义切面*//*** 环绕切点* @param*///注解修饰的方法的返回结果//切面逻辑,收集日志什么的//这个别忘记了//标准三部曲,拿取注解//获取方法参数。
2024-01-16 10:19:27
559
原创 @Autoware和@Resource区别
(1)@Autowired来自Spring框架,因此只对Spring框架的IOC容器生效,如果涉及到更换框架,需要修改代码。(2)@Resource的注入顺序刚好相反,先按照bean的名字(byName),再按照bean的类型(byType)。(1)@Autowired的注入顺序是先按照bean的类型(byType),再按照bean的名字(byName)。(1)@Autowired可以作用在属性上,构造函数上,setter方法上。(2)@Resource是JDK提供的,是一种规范,所有的IOC容器都支持。
2024-01-16 07:57:27
1029
原创 MySQL分库分表
加入MyCat中间件之后,应用程序只需要访问MyCat即可,底层的访问数据库的逻辑,都是由MyCat做的,但是我们需要配置下。
2024-01-14 15:21:23
593
原创 MySQL的各种日志
简称BINLOG日志,记录了所有的DDL(数据库定义语言)和DML(数据操作语言)语句,但是记录SELECT语句和SHOW语句。
2024-01-13 11:21:49
735
原创 Docker-阿里云镜像配置
刚安装的docker一般没有docker/daemon.json这些,需要自己新建。重启docker: systemctl restart docker。重新加载配置: systemctl daemon-reload。
2024-01-12 18:00:07
683
原创 EasyExcel+多线程实现大数据量
第二点其实也不用担心,只需要把BATCH_COUNT参数传进new PageReadListener()的构造函数就可以了,这样每次读取数据到内存中的数量就是BATCH_COUNT条,默认BATCH_COUNT=100,我这里设置成一千,最后不足一千也会读取完然后入库。在没有任何校验逻辑的情况下,导入了90万数据,时间大概半分钟多一点,速度还是很快的。这里应该是会涉及到数据库连接池的问题,需要限制连接的数量,不能将资源都分给文件上传。2、批量入库问题,如果最后一批数据不足临界值怎么解决。
2024-01-11 09:39:31
1684
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人