- 博客(121)
- 收藏
- 关注
原创 Redis面试题
Redis 作为单进程服务,虽然性能较高,但存在明显局限:读写性能受限于单个服务器的 CPU 和内存上限,且一旦服务器故障,外部服务将无法访问,高可用无法保障。多维度数据统计:如记录不同地区的视频访问量,以视频 ID 为 key,地区为 field,访问次数为 value,每次访问时对对应 field 执行自增操作,实现多维度统计。单机内存有限而数据量增长无限,直接将数据按分配到不同节点的方式,在节点数量变化时(如扩容 / 缩容),会导致所有数据的存储节点重新计算,引发全量数据迁移,成本和风险极高。
2025-10-24 01:53:13
736
原创 消息队列常见面试题
(3)rocketmq:金融、电商等核心业务,适用于对数据一致性、可靠性要求极高的场景。(1)kafka:大数据、日志处理、实时流处理(网站活动追踪、监控数据等)(2)rabbitmq:适合初创公司或传统企业,简单可靠,能满足大部分场景。(4)Apache Pulsar面向云原生,快速发展中。
2025-10-19 17:34:26
438
原创 jvm面试题
其中H区是G1独创的内存区域,专门存放大对象,大对象判定当对象大小超过0.5个Region时,被认定为大对象并放入H区,H区的好处是可以及时回收大对象,因为Old区的回收是比较低频的,又想要尽快回收大对象,就把它放到H区,它的回收是比较高频的。设置并行回收线程数(默认为CPU的核心数),因为该线程是纯计算操作,属于cpu密集型,只需要把cpu打满,不需要太多线程,太多还会带来线程切换的消耗。原理:G1 基于停顿预测模型,根据预期时间动态选择回收 Region 集合,避免全堆回收导致的长停顿;
2025-10-19 16:42:13
271
原创 线程池参数设置
DiscardOldestPolicy:丢弃队列中最老的任务,适用于实时性高的任务。IO密集型任务:通常设置为CPU核心数*2,或通过测试调整以充分利用CPU资源。CPU密集型任务:设置为CPU核心数+1,避免过多的线程导致上下文切换。CallerRunsPolicy:让提交任务的线程执行任务,降低提交速率。IO密集型任务:设置较长时间(如60s),避免频繁创建和销毁线程。DiscardPolicy:丢弃任务,适用于不重要的任务。无界队列:适用于任务数不稳定但不会无限增长的场景。
2025-10-13 16:45:42
371
原创 ReentrantLock原理
底层是基于AQS实现的,AQS能解决两个问题:(1)临界点的同步状态竞争的问题(2)没有抢占锁的线程排队等待的问题。非公平模式下新线程可能会直接抢占锁,而不需要排队等待,所以它的效率会比较高,但是可能会导致饥饿的问题,而公平锁模式是严格按照FIFO的顺序来分配。可重入,公平锁和非公平锁,相比synchronized提供了更加灵活的机制,如可中断、超时获取锁、尝试获取锁一些高级功能,那它的底层实现呢?会更新state的值,并唤醒队列中的下一个节点,重新尝试来竞争锁。ReentrantLock原理。
2025-10-13 14:31:28
440
原创 Mysql MVCC
那历史版本怎么来的,是通过undo log ,数据库中只存了最新的一条记录,然后通过undo log记录反向操作(如insert一条数据,就在undo log中delete一条数据,update一条数据就在undo log留旧值),所以需要老版本时只要顺着这些日志往回找就可以,所以一条记录和undo log就串成了一条版本链。(具体就是自己改的永远能看,比自己再提交的能看,还没提交的不能看)总结,MVCC的核心是快照读,Undo log是历史版本的支撑,ReadView决定谁能看那个版本。
2025-10-13 08:55:44
252
原创 深入理解CAS
CAS(Compare And Swap比较和交换),是非阻塞同步的实现原理,它是CPU硬件层面的一种指令,从CPU层面能保证“比较与交换”两个操作的原子性。CAS操作包括三个参数:内存值(内存地址值)V、预期值E、新值N,当CAS指令执行时,当且仅当预期值和内存值相同时,才更新内存值为新值,否则就不执行更新。CAS在java.util.concurrent.atomic类、Java AQS、CurrentHashMap等是实现上有非常广泛的应用。
2025-10-05 22:56:57
278
原创 ThreadLocal
如果key使用了弱引用,假设业务代码中使用完了ThreadLocal,threadLocal ref被回收了,由于ThreadLocalMap只持有ThreadLocal的弱引用,没有任何强引用指向threadLocal实例,所以treadLocal实例被gc顺利回收,此时Entry中的key=null。JDK早期:ThreadLocal是这样设计的,每个ThreadLocal都创建一个Map,然后用线程作为Map的key,要存储的局部变量作为Map的value,这样就能达到各个线程的局部变量隔离的效果。
2025-10-05 21:24:32
853
原创 文档中台常见问题
对于目录无法动态生成的问题,解决办法是我先生成一个基础版的pdf,此时文档内容已动态生成,然后再对基础版的pdf解析为对应的xslt-fo,在它的基础上动态生成目录内容,最后在转换为pdf。(3)使用xslt转pdf时,由于pdf的分词算法只根据按单词划分进行换行操作,这样就会导致如果内容是一段长的字母和数字串,会被默认为一个单词,导致内容太长在表格中不会自动换行的问题,解决办法判断单元格的宽度,在文本内容中插入换行符来完成换行操作。(6)大文档上传:分片上传、断点续传、合并。
2025-09-23 14:48:01
257
原创 MYSQL分页查找
因为二级索引的数据量少,只有索引和主键,所以子查询中可以直接得到id,不需要回表,然后将子查询得到的id,再去主键索引查询速度快,数据量小。优化前的数据通常会直接全表扫描主键索引,而主键索引包含全部的数据,数据量较大成本高。(1)记录当前页最后一条数据的id,下一次请求带上,这种方式优点轻、快,不用跳页,适合下拉加载这种连续滚动翻页,不能跳页,比如直接跳到第100页,因为你不知道前面第99页的最大ID是多少,这种本质上就是游标分页,以最大ID为锚点,继续往下查找。
2025-09-22 11:35:19
211
原创 电商项目实战总结
然后rocketmq会回查订单状态,如果超过最大次数,就会取消订单,如果支付成功就会RollBack,消息取消,后续就不会取消的订单了,如果未支付 ,记录回查次数后,返回UNKNOW状态,等待下次回查。迁移的过程,我们是逐表批次删除,对于每张订单表,先从MySQL从获得指定批量的数据,写⼊MongoDB,再从MySQL中删除已写⼊MongoDB的部分。在分库分表时,为了让B+树的高度控制在一定范围,保证查询的性能,表中 数据往往不宜超过2000w条,分表数量应为2的幂次方,这样迁移的数量最少。
2025-09-21 21:58:24
454
原创 分布式事务
网络分区,可以这样理解,在分布式系统中,不同的节点分布在不同的子网络中,有可能子网络只有一个节点,在所有网络正常的情况下,由于某些原因导致这些子节点之间的网络出现故障,导致整个节点环境被切分成了不同的区域,这就是网络分区。C:一致性,数据在多个副本中保持一致。可以理解成两个用户访问系统A和系统B,当A的数据有变化时,及时同步给B系统,让两个系统看到的数据是一致的。由于CAP中一致性C和可用性A无法兼得,eBay的架构师提出了BASE理论,它是通过牺牲数据的强一致性,来获得可用性。1、什么是CAP定理。
2025-09-19 01:41:31
213
原创 电商核心业务
总的来说, 对于创建订单的服务,可以通过预先生成订单号作为主键,利用数据库中主键唯一性特性,避免重复写入订单,实现创建订单服务的幂等性。对于更新订单的服务,可以通过一个版本号机制,即在每次更新数据之前校验版本号,以及在更新数据的同时自增版本号这样的方式来解决ABA问题,以确保更新订单服务的幂等性。生成ID需要保证在高流量高并发分布式场景下订单ID全局唯一,并具有趋势递增、安全性的特点.所以需要提供一个生成ID的服务,在点击下单后进入订单页前,先调用生成ID的服务获取到ID后点击提交订单,才会生成订单。
2025-09-17 19:56:54
229
原创 wait和notify为什么要在synchronized代码块中
线程调用wait方法会把线程放到监视器的wait set中,notify会唤醒wait set中的阻塞线程,如果没有synchronized就不会在对象的monitor中形成wait set,所以wait和notify就没意义了。wait/notify 是为了在持有锁的前提下,让线程主动让出锁并等待某个条件成立,否则只能“忙等”或“死等”。如果队列满了,生产者不能继续放,但它又拿不到锁,也就无法检查“队列是否不满”;如果队列空了,消费者不能继续拿,但也无法等待“队列不空”;
2025-09-17 02:17:21
219
原创 电商系统常见问题及解决方案总结
但是当用户打开“我的订单”这个页面的时候,它的查询条件是用户ID,由于这里没有订单ID,因此我们无法知道所要查询的订单具体在哪个分片上,也就没法查了。这个问题的解决办法是,在生成订单ID的时候,把用户ID的后几位作为订单ID的一部分。另外在分库分表时根据业务场景可能存在主从表,比如订单表和订单商品表,在分库分表时这两张表可以都按照订单id来分片,这样二者就可以分在同一个表中,就可以在查询订单时同时去查询对应的订单商品,而不需要再去另外分片查找订单商品。需要注意的是分库分表时,应该尽量使用2的幂来分库分表。
2025-08-17 17:42:05
447
原创 word生成问题总结
但是生成的word表格的列宽并不一定会和设置相同,实际上它会设置页宽的影响,表格的列宽最终会按照(页宽-页变距)*表格列宽占总列宽的比例,所以上面代码实际上设置的是各列宽占表格总宽度的比例,实际大小和页宽有关。但使用poi word设置列宽时需要转换为单位缇,这是因为Word文档的底层XML(OOXML)中,列宽、行高、图片尺寸等均以缇为单位存储,Units.pointsToMaster即可完成转换。
2025-08-07 16:56:11
4318
原创 分布式文件系统Minio
MinIO 是一个开源的高性能分布式对象存储系统,专为云原生和大规模非结构化数据存储而设计。它兼容 Amazon S3 API,支持海量数据的存储与管理,适用于图片、视频、日志文件、备份数据等场景。另外,Minio使用go语言开发的,go语言天然就有跨平台特性和性能高的特点.
2025-03-16 14:45:23
838
原创 图片上传保存问题
但在开发中发现没有得到预期效果,这是由于xml内容并未传入导致的,最后经过调查发现,当xml中写入多个图片,xml无法保存在数据库中。2、解决了请求过大的问题后,由于在程序中xml是使用字符串来处理并存储在数据库中,还要防止字符串太大的问题。需要注意的是:流的真正优势在于处理外部数据源时逐步加载内容,而非处理已加载到内存的字符串。在处理字符串时,如果将整个字符串一次性转换为流且不分块处理,其内存占用与直接使用字符串几乎相同,甚至可能略高(因流对象本身有额外开销)。3、数据库存储使用text或byte。
2025-03-14 00:54:03
188
原创 个人网站部署
我的个人网站是react项目,具体搭建步骤:补充:本博客的前提是已经准备好服务器、域名以及备案。1.1 安装Node.js和npm1.2 将本地项目打包通常打包后会生成build文件夹,本项目采用了next.js,打包后生成了.next.js文件夹。1.3 安装项目依赖将本地项目上传到服务器(假设上传到 /var/www/next-app)
2025-03-12 01:22:28
285
原创 Linux常用命令
lsls 命令是Linux中最常用的命令之一,它用于列出指定目录的内容,包括文件和子目录。常用参数:-l:以长格式列出目录内容,显示详细信息。-a:列出所有文件,包括隐藏文件(以"."开头的文件)。-h:将文件大小以人类可读的格式显示(如K、M、G)。-R:递归地列出目录内容,包括子目录中的内容。-t:按修改时间排序文件。pwd 命令用于显示当前用户所处的工作目录的完整路径。cd 命令用于切换工作目录。常用参数:…:返回上一级目录。~:切换到当前用户的主目录。
2025-03-06 13:24:30
979
原创 Redux实现Token持久化
业务背景: Token数据具有一定的时效时间,通常在几个小时,有效时间内无需重新获取,而基于Redux的存储方式又是基于内存的,刷新就会丢失,为了保持持久化,我们需要单独做处理。使用redux+LocalStorage解决,当浏览器被刷新,可以先查看localStorage中是否存储token,如果没有再进行初始化。
2024-06-30 17:19:29
339
原创 React学习总结
(1)在React中如果调用函数比如代码中this.saveType不加括号,会将该函数返回,下次发生onChange就会调用该函数;如果是this.saveType()加了括号,那么该函数在渲染时就会执行一次,而且返回的是该函数的返回值,所以上述代码中saveType函数中返回了一个回调函数来实现返回函数的效果。(1)原生JS操作DOM繁琐,效率低。
2024-06-27 10:32:44
305
原创 Spring和SpringBoot的特点
(2)场景启动器starter:SpringBoot对常用的场景都进行了整合,将这些场景中所需的依赖都收集整理到一个依赖中,并在其中添加默认的配置,使项目开发中只需导入一个依赖,即可实现场景技术的融合。(1)约定大于配置:SpringBoot对日常开发中比较常见的场景都提供了默认配置,并基于自动装配机制,将场景中通常必须的组件都注册好,以此来减少配置。(5)生产级的特性:SpringBoot提供了一些如健康检查、监控指标、外部化配置等很有用的生产运维型的功能特性。
2024-06-10 21:52:13
510
转载 Redis调优-BigKey问题
Redis中的大key,实际上指的是key所关联的value值特别大,比如字符串过大或者是某种数据结构(如hash,list ,set,zset)中存储了过多的元素。详情可参照《阿里Redis开发规范》,一般来将,String类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。
2024-05-18 19:07:39
81
原创 Redis总结
计数器在网站中的作用至关重要,例如视频网站有播放数、电商网站有浏览数,为了保证数据的实时性,每一次播放和浏览都要加1的操作,如果并发量很大对于传统关系型数据的性能是一种挑战。赞/踩、粉丝、共同好友/喜好、推送、下拉刷新等是社交网站的必备功能,由于社交网站访问量通常比较大,而且传统的关系型数据不太适合保存这种数据,Redis提供的数据结构可以相对比较容易地实现这些功能。Redis采用了链式哈希来解决哈希冲突,链式哈希的局限性很明显,随着链表的长度的增加,查询这一位置上的数据的耗时就会增加。
2024-05-17 21:44:11
825
2
原创 Spring,SpringMVC,SpringBoot知识总结
Spring Core 模块提供了 Spring 框架的核心功能,包括依赖注入(Dependency Injection即DI)和控制反转(Inversion of Control即IOC)等。这些功能是 Spring 框架的基础,许多其他 Spring 模块都依赖于 Spring Core 模块。具体可参考https://zhuanlan.zhihu.com/p/448716053。
2024-05-13 12:55:54
1218
原创 JVM面试题
1.Serial回收器:串行回收Serial收集器采用复制算法、串行回收和"stop-the-World"机制的方式执行内存回收。Serial收集器作为HotSpot中client模式下的默认新生代垃圾收集器。除了年轻代之外,Serial收集器还提供用于执行老年代垃圾收集的Serial Old收集器。Serial Old收集器同样也采用了串行回收和"Stop the World"机制,只不过内存回收算法使用的是标记-压缩算法。Serial old是运行在Client模式下默认的老年代的垃圾回收器。
2024-05-09 17:53:58
862
原创 缓存击穿、缓存穿透、缓存雪崩
缓存穿透是指访问的数据在缓存中并不存在,请求会不经过缓存直接访问后端存储系统。通常情况下,这些请求对应的数据在后端存储中也不存在,因此无论如何都无法从缓存中获取到数据,每次请求都会直接落到后端存储系统上,导致了不必要的资源浪费和系统压力增加。缓存穿透可能是由于恶意攻击、恶意请求或者缓存系统配置不当等原因导致的。
2024-05-04 21:06:25
1256
原创 类加载子系统
为什么要自定义类加载器?● 隔离加载类● 修改类加载的方式● 扩展加载源● 防止源码泄漏用户自定义类加载器可以从非标准位置(如数据库、网络、特定文件系统等)加载类文件,从而实现动态加载、远程加载等功能。并且还可以在加载类文件时执行一些额外的逻辑或增强功能,比如加密解密、访问控制等来防止源码泄漏。
2024-04-18 16:35:02
804
原创 排序算法总结
优化一:当算法执行过程中数组已经是有序数组了,这是就没有必要继续执行完n-1趟外循环,可以直接结束了。具体实现我们可以通过一个标志,来记录当前一趟外循环,在遍历过程中是否发生交换,如果没有交换说明,数组已经是有序数组,可以跳出循环了。优化二:在某种情况下,如果进行了若干次排序后,后面的若干个数已经是有序的,那么下一趟排序只需要比较前面无序的那部分即可。冒泡排序是经典的入门算法,可以说每个人都会写它,但它也可以优化。在面试中让写冒泡排序,不要简单以为就是让你写两重循环,可能是在考察你对它的优化。
2024-04-15 21:52:05
340
原创 计算机网络常问面试题
HTTP代表“超文本传输”协议,它是一种用于在网络上传输网页、图片和其他资源的协议。当你在浏览器中输入一个网址或者点击一个链接时,你的计算机会向服务器发送一个HTTP请求,然后服务器会回复一个HTTP响应,将网页内容发送给你的浏览器,然后浏览器会把这些内容呈现出来。综上所述,HTTPS是一种更加安全的协议,适用于涉及敏感信息和隐私保护的网站和在线交流。● HTTPS在HTTP的基础上加入了安全性,通过加密数据来保护你的隐私和安全。● HTTP是一种用于在网络上传输数据的协议,但不够安全。
2024-04-14 21:45:46
813
原创 Queue,Deque,Stack的常用方法
这里需注意,对于pop()和push(),大家第一反应肯定是Stack,而Stack里的pop()和push()是对末元素操作,Deque里的pop()和push()是对队首元素操作。Stack继承了Vector,出于各种原因,Vector现在不建议使用了,因此官方文档里推荐用Deque代替Stack,Deque里有push()和pop()方法正是为了取代Stack。add()、offer()、peek()、poll()、remove()与Queue相同。pop():返回并弹出队列首元素。
2024-04-13 21:11:12
356
原创 SpringBoot Cloud Gateway
大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用。每个业务都会需要鉴权、限流、权限校验、跨域等逻辑,如果每个业务都各自为战,自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝、亚马逊打开一。
2024-04-13 21:04:02
1304
原创 MySQL优化
关于MySQL优化,我们可以根据一条SQL的执行流程需要经过哪些环节,通过这些环节思考对应的优化策略。SQL优化中最主要的就是查询优化。其中关联查询太多可能是由于数据库设计不合理,可以根据数据库设计的范式准则,适当增加冗余,减少需要关联的表。
2024-04-06 12:33:19
1154
1
原创 Nacos注册中心
官方:一个更易于构建云原生应用的动态服务发现(Nacos Discovery )、服务配置(Nacos Config)和服务管理平台。集 注册中心+配置中心+服务管理 平台服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理。
2024-04-03 16:38:55
640
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅