- 博客(44)
- 收藏
- 关注
原创 缓存三大问题详解与工业级解决方案
缓存系统三大经典问题及解决方案摘要: 缓存系统面临三大核心问题:1)缓存穿透(查询不存在数据导致数据库压力)解决方案包括布隆过滤器、空值缓存和参数校验;2)缓存击穿(热点key失效时的并发冲击)可通过分布式锁、本地锁、数据预热和永不过期策略应对;3)缓存雪崩(大量key同时过期或缓存宕机)建议采用随机过期时间、多级缓存架构和缓存预热措施。工业级场景推荐组合方案:参数校验+布隆过滤器+多级缓存+分布式锁,并配合异步更新机制,可有效保障系统高可用性。
2025-07-09 15:03:37
702
原创 Redis的多并发实际业务场景下的使用分析:布隆过滤器
本文介绍了布隆过滤器的原理及其在Redis缓存中的实践应用。布隆过滤器是一种空间高效的概率数据结构,通过位数组和哈希函数快速判断元素是否存在。文章详细讲解了布隆过滤器的工作流程,包括插入和查询操作,并解释了"可能存在"和"一定不存在"的原理。通过Java代码示例展示了如何在项目中集成布隆过滤器,包括Redisson的配置和使用。重点阐述了布隆过滤器在缓存系统中的应用,提出"三级防护体系"的最佳实践方案,以商品详情页为例,说明如何通过布隆过滤器防止缓
2025-07-09 09:25:23
521
原创 Redis常用数据结构以及多并发场景下的使用分析:Sorted List类型
这篇文章分析了Redis中的Sorted List(有序集合)数据结构。其底层实现根据数据量大小采用两种方式:元素较少时使用压缩列表(ziplist),元素较多时采用跳表(skiplist)结合哈希表的双结构设计。跳表通过多层索引实现高效的范围查询和排序,时间复杂度为O(log n),相比平衡树实现更简单且性能稳定。文章还通过示例演示了跳表的插入过程,并对比了跳表与其他数据结构的优势。
2025-07-08 16:00:20
1130
原创 Redis常用数据结构以及多并发场景下的使用分析:Set类型
本文分析了Redis中Set类型的底层实现与使用场景。Set底层采用整数集合(intset)和哈希表(hashtable)两种结构,当元素为整数且数量较少时使用连续数组存储,否则转为哈希表实现。Set具有高效的查找、插入和删除操作(O(1)时间复杂度),并支持集合运算。文中通过三个典型用例展示了Set的实际应用:在线用户统计(去重)、用户标签相似度计算(交集运算)和秒杀活动参与者去重(唯一性校验)。这些场景充分利用了Set的自动去重特性和集合运算能力,在保证数据唯一性的同时提高了系统性能。
2025-07-07 19:43:44
733
原创 Redis常用数据结构以及多并发场景下的使用分析:list类型
本文介绍了Redis中List数据结构的实现原理及其应用场景。Redis List在不同版本中的底层结构演变:早期使用ziplist+linkedlist,3.2版本后引入quicklist(ziplist+linkedlist组合),5.x后成为默认实现。quicklist结合了ziplist内存紧凑和linkedlist插入删除快的优点,通过多个ziplist节点双向连接实现。文章还列举了两个典型应用场景:1)维护用户最近访问记录(利用LPUSH和TRIM命令);2)构建简单消息队列(LPUSH/RPO
2025-07-07 15:02:25
761
原创 Redis常用数据结构以及多并发场景下的使用分析:Hash类型
Redis Hash结构在多并发场景下的应用优势 摘要:本文对比了Redis中Hash和String类型的数据结构,重点分析了Hash在结构化数据存储上的优势。通过商品库存管理案例,展示了Hash如何统一管理对象属性(1次网络往返+内存紧凑)。在秒杀系统设计中,提出使用Hash存储商品库存(Key: seckill:stock:date,Field: productId),配合Lua脚本实现原子化库存扣减,以及HMGET命令批量查询库存。测试结果表明,Hash结构在并发场景下能有效避免热点Key问题,提高系
2025-07-07 10:44:27
905
原创 Redis常用数据结构以及多并发场景下的使用分析:String类型
本文介绍了Redis中String类型的基本用法和典型应用场景。String类型作为简单的key-value存储,常用于缓存对象(如用户信息)、计数器(如文章浏览量统计)和分布式锁的实现。分布式锁通过SET key value NX EX time命令实现原子性加锁,配合Lua脚本确保安全解锁。文章还提供了Java代码示例,并解释了Redis单线程特性如何保证分布式锁的安全性。String类型因其简单高效的特点,成为Redis中最基础且实用的数据结构之一。
2025-07-05 20:41:43
341
原创 热点检测中的算法介绍 Lossy Counting、Count-Min Sketch 、HeavyKeeper以及HeavyKeeper的java实现
【热点数据检测算法分析】本文对比了三种热点数据检测算法:Lossy Counting适用于频率大于阈值的数据挖掘,通过bucket划分和误差控制实现;Count-Min Sketch采用二维数组和哈希映射估算频率上界;HeavyKeeper则通过概率性替换机制和最小堆维护实时Top-K结果,更适合流式数据处理。重点解析了HeavyKeeper的Java实现,包含多层哈希表、衰减机制和最小堆等核心组件,适用于热点Key检测、流量分析等实时场景。
2025-06-23 09:27:06
754
原创 java 21虚拟线程vs传统线程 原理分析以及具体测试例子去分析性能提升
摘要:Java虚拟线程深度解析 本文系统介绍了Java 21引入的虚拟线程技术。虚拟线程是JVM用户态实现的轻量级线程,相比传统OS线程具有显著优势:内存占用从MB级降至KB级,支持百万级并发;在I/O阻塞时能自动挂起释放资源,通过N:M映射机制实现高效调度。文章通过代码示例展示了虚拟线程与传统线程的差异,并设计微服务测试案例对比两者性能。虚拟线程本质是Java对协程的实现,其核心原理在于任务挂载/卸载机制和Continuation状态保存。适用于高并发I/O场景,但需注意CPU密集型任务仍需传统线程。配置
2025-06-17 17:32:01
1021
原创 MySQL 5种 批量更新介绍以及性能对比测试
本文对比分析了MySQL中五种批量更新方式的性能差异: INSERT ON DUPLICATE KEY UPDATE - 适用于重复值较多的场景,仅更新冲突字段索引 CASE WHEN - 最推荐的批量更新方式,单条语句完成多行更新 临时表+JOIN - 适合大数据量更新,但需额外创建临时表 REPLACE INTO - 性能较差,先删除再插入所有索引 事务批量提交 - 减少事务开销但本质上仍是单条更新 测试环境采用10万条用户数据,重点比较更新1万条记录的性能。通过具体SQL示例展示了每种方法的实现,并分
2025-06-16 14:24:55
974
原创 多线程下 到底是事务内部开启锁 还是先加锁再开启事务?
摘要 本文探讨了事务与锁配合使用时常见的并发安全问题。通过电商下单场景示例,分析了一种典型错误模式:在事务内部加锁但提前释放锁,导致另一个线程能看到未提交的事务状态,从而引发重复下单问题。文章指出问题根源在于锁未覆盖整个事务范围,并提供了两种改进方案:将锁放在事务外部保护整个事务,或使用分布式锁确保事务完成后再释放锁。核心建议是锁的范围应完全包含事务操作,避免中间状态暴露引发的并发问题。
2025-06-14 19:31:36
244
原创 使用Spring Cloud Stream 模拟生产者消费者group destination的介绍(整合rabbitMQ)
这篇文章介绍了Spring Cloud Stream在微服务中的整合使用,通过统一开发模型简化MQ消息处理。主要内容包括: 使用Spring Cloud Stream可以跨Kafka/RabbitMQ/RocketMQ实现一致代码,只需关注destination+group+Consumer; 展示了实际整合步骤,包括pom依赖引入、配置destination和group的YML设置; 提供了生产者(StreamBridge)和消费者(@Bean Consumer)的代码示例; 说明自动ACK模式配置...
2025-06-09 19:39:54
923
原创 令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
摘要:限流与限制并发机制解析 本文系统讲解了限流与限制并发的核心概念、业务场景及实现方案。通过餐厅厨房的生动比喻,阐明限流类似控制顾客进门频率,限制并发则是控制后厨同时处理的订单量。技术实现层面详细介绍了两种主流方案:令牌桶算法(通过Redis实现速率控制)和滑动窗口算法(基于ZSET结构记录时间窗口请求)。文章还提出了双注解实现方案,并计划优化为统一注解方式。测试案例展示了10并发场景下仅2请求通过的情况,验证了限流效果。最后针对滑动窗口实现的时间戳问题提出了改进思路,为高并发系统设计提供了实用参考方案。
2025-06-06 19:08:06
1197
原创 redis分布式锁的实际业务使用和底层基本原理 对比 lock trylock
本文通过支付业务代码分析Redis分布式锁的实现原理。Redis使用hash结构存储锁数据(线程ID和重入计数),Redisson客户端提供lock和tryLock方法,其中带参数方法不启用Watchdog自动续期机制,而无参方法会启动后台线程定期续期。文章对比了四种加锁方式的特点及适用场景:lock()适用于必须执行的长时间任务;tryLock()适用于瞬时高并发场景;带参数的tryLock()适合限定等待时间的任务。理解这些机制有助于在不同业务场景中选择合适的分布式锁实现方式。
2025-06-05 13:49:34
862
原创 基于 ThreadContext 封装多个“业务上下文类”以实现可复用、易拓展
本文提出了一种基于ThreadLocal的线程上下文参数传递解决方案。通过定义ThreadContext作为底层线程隔离存储容器,使用ConcurrentHashMap存储键值对,并提供设置、获取、清除等方法。在此基础上,可以创建各种业务专用的Context工具类(如UserContext、BusinessContext等),这些工具类只需专注于业务字段的存取,无需修改底层逻辑。该方案具有可复用性和易扩展性,新增业务上下文时只需添加对应的封装类即可。ThreadContext管理通用存取逻辑,各业务Cont
2025-06-03 13:42:38
137
原创 带你用实际的业务代码去分析多线程下的常见错误以及改进方法
本文总结了多线程编程中的常见错误及改进方案。主要问题包括:1) Future.get()的阻塞调用导致异步变同步,应先提交所有任务再统一获取结果;2) 方法内频繁创建线程池造成资源浪费,建议使用全局线程池;3) 无界队列可能导致OOM,应使用有界队列;4) 非必要使用AtomicInteger带来性能损耗,简单计数场景可用普通变量替代。文章通过具体代码示例展示了问题所在,并给出了优化后的实现方案,帮助开发者避免在多线程业务开发中踩坑。
2025-06-02 08:15:11
701
原创 在 SpringBoot+Tomcat 环境中 线程安全问题的根本原因以及哪些变量会存在线程安全的问题。
在Tomcat+SpringBoot环境中,线程安全问题的根源在于Tomcat的多线程处理模型与Spring默认的单例Bean模式结合。当多个HTTP请求并发处理时,多个工作线程会同时访问同一个单例Bean实例,若该Bean包含可变的实例变量、静态变量或非线程安全的集合对象(如HashMap、ArrayList等),就会产生线程安全问题。通过测试案例对比可见,单例模式下多个线程会共享成员变量,而多例模式或局部变量则能保证线程安全。
2025-06-01 14:04:39
639
原创 【ThreadLocal实践二】带你用实际的业务去理解ThreadLocal的使用以及缓存的思想
【ThreadLocal实践二】带你用实际的业务去理解ThreadLocal的使用以及缓存的思想 ThreadLocal 实现了「线程隔离」 每个线程拥有自己独立的「存储空间」来记录与某个 ThreadLocal 相关联的值。该怎样去利用这个特性在多线程编程下?希望结合这两篇文章 你能对ThreadLocal的实际使用有更多的理解!
2025-01-22 07:38:08
276
原创 线程池使用不当的危害(三):如何正确根据业务去孤立使用线程池以及如何确定多个线程的执行正确与否?
该文章整理了实际线程池的使用例子以及在公司中如何根据业务去维护线程池的内容。通过以上的方式定义了一个可以维护的根据业务类型去创建线程池的工具类,以及给出了如何使用这个工具类的具体场景。希望这篇文章对你如何实际使用线程池有帮助!
2025-01-20 13:50:04
336
原创 Stream流实践(六):文本频率排序(Most frequently used words in a text)
本文会用一个例子去讲解Stream流 针对文本频率排序的问题的java实现。
2024-12-19 13:16:05
170
原创 【ThreadLocal实践一】带你用实际的业务去理解ThreadLocal的使用以及缓存的思想
考虑以下的业务背景,用户在一个请求中需要发起超过千次以上的批次请求,程序需要对每一批次的每一笔数据都进行校验、查库、落库。(也就是理解为一个Http进程中会处理上千次的重复查库)原本的业务代码是没有做任何控制,每一笔数据都会查询数据库,导致的问题为响应时间过长 批次超过了设定的阈值响应时间。
2024-12-12 11:25:50
320
原创 设计场景实际去体验 rabbitmq 重试机制。场景设计->消息流转模型设计->java代码实现
设想一下场景:消息发送的客户端,发送消息到交换器,交换器分发消息到消费者,此时我们的业务中的mq的消费者发生异常,消息没有正常消费。此时客户并不知道消息出现问题,我们也不能要求客户重新发送消息给消费者了,此时如何引入重试机制,使得消费者出现异常后,该条异常的消息能够重试n次,重新回到消费者队列,以供消费者重新使用呢?
2023-11-05 16:29:29
308
原创 手把手教你结合chatGPT api构建前后端项目(后端springboot+前端javascript)
你可以从这篇文章学到什么?1、简单web应用构建-》我将结合以进行过程演绎 2、后端 springboot 结合 chatGPT api 简单构建后端应用 3、前端使用parcel构建简单前端javascript项目
2023-10-24 08:01:41
910
原创 Stream流实践(五):使用group by然后紧跟sum sort等操作
本文会用几个例子去讲解Stream流 group by基本用法,以及group by分组之后对于分组数据的汇总、排序等操作
2023-03-30 17:48:32
6936
原创 Stream流实践(四):流中如何保留重复元素?(基本类型 对象)
我们已经非常熟悉了,Stream流中可以采用distinct()去除重复元素。那么反过来思考下,如何保留重复元素呢?例如:{ 1, 2, 1, 3, 4, 4 }输出结果:[1,4]
2023-03-27 10:51:24
732
原创 Stream流实践(三):多重嵌套对象的数据汇总
stream流实践,多重嵌套对象的数据计算。有一类似场景:c包含b 、b包含a ,计算 list中的所有数值?
2023-03-06 11:23:07
1060
原创 线程池使用不当的危害(二):使用jconsole图像化展示局部、类变量线程池的创建
在上一篇文章中我们讨论了应该如何使用线程池的问题,得到了不能随意在代码中new 局部变量的线程池,相信你已经知道了基本的使用规则。那么本篇文章就是带你使用工具去图像化的,直观化的体验web程序在相对的并发下,如果不复用线程池,无限制的创建局部的线程池,会带来的问题。
2023-02-28 17:46:31
227
原创 线程池excutor submit 两种方式 对于异常的处理问题的探究
不知大家在对待excutor or sumbit方式执行的线程池,内部出现异常是否要catch住这个问题有没有思考?例如,我常在代码中发现以下处理方式:
2023-02-24 16:21:04
1722
原创 线程池使用不当的危害(一):局部变量线程池、类变量线程池的使用方法
本文探索了局部变量线程池、类变量线程池使用上的坑,和可能导致的问题。最后根据经验和实际上线的项目,给出当前我的线程池使用经验,以及某些创建线程池的变化,供大家学习。
2023-02-07 17:50:44
1558
6
原创 Stream流实践(二):list 对象数组根据某字段去重的三种基本思路
相信大家对于list简单数组的去重很熟悉了,例如以下代码那我们来探讨下,对于list中保存为对象的数组,根据内部对象的某一个字段去重有什么好的思路呢?
2023-02-07 15:40:42
31604
2
原创 针对集合、map浅拷贝深拷贝的问题分析(以实际代码说明)
本文针对集合、map浅拷贝深拷贝的问题分析(以实际代码说明)两者的区别:浅拷贝:直接引用原对象的内存地址,导致修改复制后的对象,原对象也被修改深拷贝:重新在栈、堆中开辟空间,内存地址不一样,内部存放的数据一样,修改复制后的对象,原对象不会影响。那么本文就是针对常见的针对集合、map的复制方法,探究他们是浅拷贝还是深拷贝!
2022-09-25 10:22:51
2757
原创 oracle, clob类型查询提示:1. 字符串缓冲区太小 2. 数据类型不一致: 应为 -, 但却获得 CLOB的解决办法
oracle, clob类型查询提示:1. 字符串缓冲区太小 2. 数据类型不一致: 应为 -, 但却获得 CLOB的解决办法
2022-08-30 21:39:22
4674
原创 责任链模式的另一种实现方式(动态注入 + 顺序执行)
本文是作者结合工作中实际的责任链的处理情况,构建了如下的代码场景:1. 责任链的实现链条是固定执行的,模拟数据必须走完所有的数据过滤的处理器(注意:责任链的实现链条是不一定固定的,这里是固定的情况)2.具体的子类的实现必须是可配置的,即可以通过@AutoWire的形式自由配置子类,假如没有配置子类,则使用基类去执行过滤.........
2022-08-14 16:28:52
1498
原创 Stream流实践(一):Stream流的方式遍历map,筛选数据
有一产品类,包含id,产品编号,产品金额。在代码中采用map方式去存储该产品,map的key是从数据库中查询出来的每一个产品的序号,value则是一个一个的map类型,问:如何筛选这个map使得代码简介好看?......
2022-08-14 15:36:53
7656
4
原创 通过数据库底层ibd文件来理解char(n) varchar(n)中n的含义
前言不知你是否还在纠结char(n) 和 varchar(n)中的n到底是最多存储 n个字符 还是 n个字节 这样的问题?那么本文将会通过mysql数据插入的场景举例 以及 查询底层数据库的存储文件xx.ibd来回答你这个问题。好的,那我们就准备开始吧!数据插入场景实践伙计们,我准备新建两张表,分别仅存储char 和 varchar类型的数据来验证是【字符还是字节】的疑惑。下面这张图是我创建的测试表:CREATE DATABASE dbtestCREATE TABLE a1(--
2022-05-17 11:04:29
485
原创 工具向:一个工具类完美解决前后端时间戳与String的转换以及LocalDateTime的带T的解决
前提:数据库中时间格式是dateTimeJAVA类中以LocalDateTime 对应数据库中的dateTime工具类:注: 默认是以毫秒为粒度 以秒为粒度需要放开秒的注释/** * @author luo qinfeng */@Componentpublic class TimeUtils { /** * 格式化传入的时间戳(毫秒) * @param timeStamp * @return */ private Str
2020-11-14 17:01:07
1204
原创 工具向: springboot 2.0.x 以及 1.0.x 引入dubbo + zkclient 依赖的那些坑
正文springboot整合dubbo以及zookeeper的时候,出现以下的错误:zookeeper not connected日志的冲突空指针基本上都是导入的依赖的问题!!注意:一下测试是基于springboot最新版本2.3.1.RELEASE 以及1.x 版本 – 1.5.12.RELEASEporm.xml<!-- 引入dobbo启动器--><dependency> <groupId>org.ap
2020-07-12 23:07:17
658
原创 详解 java中 动态代理的两种实现方式(具体案例分析)
目录一. 简介二. 基于接口的动态代理核心:案例分析:案例的理解:三. 基于子类的动态代理核心:案例分析:案例的理解:四. 总结:一. 简介代理这种模式其实就是在不改变目标对象方法的情况下对方法进行增强 本文将从基于接口以及基于子类的方式来讲解动态代理二. 基于接口的动态代理核心: JDK官方提供的Proxy类中的newProxyInstance方法案例分析:这就是需要方...
2020-05-04 20:11:31
698
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人