- 博客(26)
- 收藏
- 关注
原创 一致性哈希
如果进行大促,订单A通过哈希他的订单ID来到bucket 1,如果增加一个bucket,那么之后再执行相同的哈希方法,则会导致订单A通过哈希他的订单ID来到bucket 2。假设bucket的个数为4,那么每次的请求都会去% 4(size),这会有一个什么问题呢,如果size增加,那么哈希去到原来的bucket的请求/数据就会更改。那么通过这个结构可以看到,我们的节点更改时不会影响全部的映射,而是去影响两个节点之间的对应值的映射,一定程度上解决了哈希导致的不一致问题。常见的分片算法, 或者说路由算法,有。
2025-10-09 09:43:02
328
原创 大文件操作思路-切分
现在我们来考虑内存不足以放下所有的内容的情况。对于不足以放下所有的内容来说,我们的思路基本为将大的内容划分为小的部分,然后再去小的部分去进行去重。由于我们主要的内存限制在比如HashSet这种数据结构里,这里又牵扯到了OS是如何对底层的文件进行读取操作的。简单来说,他是可以不去一次性读取文件内容的。所以我们可以对文件内容进行分片。那么我们的思路就变成了将大文件通过分片算法划分为小文件,然后对。
2025-10-02 20:36:06
355
原创 大文件去重 (上)
由于篇幅问题,这里只去考虑内存放得下的部分,整体思想就是通过HashSet来去标识唯一存在。但是这样不够省内存,为了去省更多的内存,我们考虑用布隆过滤器,但是这样会带来精度丢失的问题。视具体情况而定。
2025-10-02 15:39:18
934
原创 从Redisson分布式锁看锁的设计思路
我们先来了解一下Redisson是个什么东西,他是一个客户端,通过网络和redis来沟通。那么他用的什么东西呢,如果你找一下他的依赖,那么就会发现netty,他通过netty来和redis沟通,这对于后边看门狗的续期,有很大的相关性。
2025-09-01 22:46:23
1074
原创 基本索引结构
本篇分享一下我对索引的理解。我们先来看一下有他能干什么,他的核心功能就是:保留一些额外的数据,让这些数据作为我们之后查询目标数据的一个向导(请记住,索引是索引,数据是数据,二者本质来说是不同的东西,索引负责查找,数据负责存储,所以他们可以杂在一起,当然也可以分开,以后在看相关内容时应该分开数据存储的结构和索引的结构,虽然有时这两个玩意可能是一个东西)。了解功能之后,我们就知道:他会引入额外的信息,这虽然有利于查询,但是可能不利于其他的操作(比如修改或者删除)他可以给我们带来查询时效率上的提升。
2025-08-27 16:41:59
861
原创 kafka基本思路即概念
首先我们在讲消息队列之前,我们需要了解一下Pub/Sub模式,即他是什么,为什么需要Pub/Sub模型。首先Pub/Sub是什么:发布者不知道接收者是谁,接收者不关心发布者是谁,他们和broker(中间分发人)共同制定主题(topic),接收者只关心主题。比如我是书店的老板(broker),我对书店的内容进行管理,发布者(pub)就相当于报刊,他们写消息给我,不关心谁收。接收者(sub)就相当于来这读书的,他通过topic来找自己需要的报刊。
2025-08-24 18:51:17
2188
原创 CS144 lab0
OK啊,这是cs144的第一个lab,他主要是让我们了解到了有关socket编程相关的内容,即操作符,TCP等相关的内容,以及流式操作的精髓,批量操作。虽然由于对cpp的不熟,导致写起来有些痛苦,但是思路是get到的,对于实现,还是要精进一下。希望我以后每周都能推进一个lab吧。
2025-08-24 11:36:43
441
原创 缓存与Redis
通俗来说,缓存就是一个数据存储的数据库,只不过他的访问速度会比原数据库更快。当一个需要复杂计算的结果被计算出来后,他就可以直接存储在缓存中,之后的请求如果想要这个结果,那么可以直接从缓存中抽取出来,这对于时间与资源都是极大的节约。下面是一些具体使用缓存的场景CPU的多级缓存。数据库查询结果缓存磁盘缓存。总的来说,需要经常访问的数据,都可以放到缓存中。没有什么最好的缓存驱逐策略,只有看自己的场景需要什么缓存驱逐策略才是最重要的。一切的一切都要从实际出发。
2025-08-21 10:18:59
1993
原创 java IO网络模型
首先来看网络是什么东西,他最核心的地方便是通信,即发消息和收消息。A给B发消息,然后B收取A发的消息。那么发消息的过程也有很多的不同,最常见的有阻塞IO,非阻塞IO,多路复用,异步IO。这里主要讲阻塞IO,非阻塞IO和多路复用。
2025-08-18 16:27:35
895
原创 面向过程与面向对象分析
摘要: 编程范式核心思想对比:面向过程聚焦算法流程,面向对象强调抽象封装。面向过程以"程序=数据结构+算法"为核心,通过分解步骤解决问题(如校园导航系统中的图算法实现);面向对象则通过类抽象现实实体,用接口规范行为、继承处理共性差异,以降低复杂度(如员工管理系统中的多态设计)。两种范式各有所长:过程式强调操作流程,适合明确步骤的任务;对象式通过层次化抽象管理复杂性,更适合大型系统构建。关键在于根据问题域特点选择合适的抽象层级和组织方式。
2025-08-16 17:39:49
749
原创 TCP连接的三次握手和四次挥手
大家可能都被问过,为什么TCP连接需要三次握手四次挥手,硬背的话可能比较痛苦,我提倡理解,所以用一个场景来说明TCP为什么需要三次握手四次挥手。
2025-08-13 16:48:32
176
原创 从ConcurrentHashMap看锁优化思路
我想,聊ConcurrentHashMap一定离不开并发,我们都知道他是为了解决HashMap的并发安全问题而生,那你有没有想过,我们在背八股的时候,都说HashTable和HashMap最大的不同便是HashTable是线程安全的,那么为什么要有ConcurrentHashMap?留下这个思考后,我们来想,造成并发安全的原因是什么?是不是不同线程同时对共享内存的访问,即我们需要一种手段来保证并发的安全性。
2025-08-13 16:10:38
2050
原创 消息幂等性
由于网络传输过程是不可信的,当遇到网络抖动的时候,最简单的解决办法就是重试,但是重试也会带来新的问题,假如下游已经收到了信息,但是我们并未收到他的response,所以我们假设他寄掉了,重新发请求(和计网发包蛮像),但是如果下游真的收到了,他就会收到两条请求,如果这是付款,那么会扣两次款,我们肯定是不能接受的。所谓幂等就是无论同一请求被重复处理多少次,他都应与执行一次的结果相同。用数学式子来说,就是f(x) = f(f(x)) 对于读操作,他天然幂等,单对于写操作,他并非幂等。我们要确保他的幂等。
2025-08-03 09:28:53
316
原创 对线程池的简单理解
这里主要是池化思想,或者说享元模式,因为java里的线程原理上依旧使用的操作系统的线程,频繁的创建,消除线程会带来额外的资源消耗,比如说system call导致的巨大的消耗,所以我们维护一个池子,你要用,从我这里拿。另外,对于线程池,他相当于对线程的一个管理,同样的思想我觉得和责任链模式中,使用一个容器来管理所有的责任链是类似的(注意,这里只是单纯指用容器管理所有的内容这种思想)。
2025-08-02 12:02:35
770
原创 Mysql 死锁分析思路
根据输出我们可以看到,事物1等待X锁,这个锁此时被事物2持有,那么拿到这个锁之后,他又去等待另一个锁,然后检测到死锁发生,把事物回滚了。我们来看事物二等待的这个锁,他还是个 rec insert intention 类型的,即插入意向锁(注意这里不要和意向锁混了哟),我一看,诶哟,我都是update语句,你哪来的。于是我又插入一条数据,用后边的entity(注:这里的entity没有加索引)作为where查询条件,这里仍然有会有死锁,只是有时候不明显,你可以多试几次,应该是可以看到索引信息的。
2025-08-01 17:23:35
843
原创 有关Mysql中的锁
随后呢,不只行,对于表,我们同样可以加锁,对于这种锁的粒度不同的内容,我们称之为。,这个玩意看名字也能看出来,当有间隙锁的时候,又有新的事物想要把新的record插入该行,那么就会获得一个间隙锁,当不同的事物插入相同间隙但是不同的值的时候,他们不会互相阻塞,比如gap lock锁了3-6,A事物想插入4,B事物想插入5,那么不会互相block。有必要聊一下这个间隙了,假设有主键值为1 , 4的record,那么对于1,他锁定的范围就是(负无穷,1] , 对于4,他的锁定范围就是(1,4]。
2025-07-27 15:43:24
380
原创 如何理解JVM中的Synchronized锁升级?
你想啊,假如说就两个线程,这个method执行起来也很快,当A线程和B线程执行时很少(注意不是没有)会同时进行,那么我就先加个乐观锁试一试吧,以CAS的方式来作为获取锁的方式,如果没有拿到锁,你先spin一会吧(spin就是空转/自旋,可以理解为一个while空循环执行,减少context switch的花销,但是同时会导致CPU资源被浪费),反正你很快就能拿到了,CPU自旋的开销可能比context switch小很多,那么就先用轻量级锁试一试。大家只需记住一个核心,用锁是有代价的,这个代价就是效率。
2025-07-22 11:55:54
519
原创 mysql基本理解思路
那么mysql中innodb存储引擎为我们提供了四种隔离级别,分别是不可提交读,提交读,可重复读,串行。最后是有关Durability持久化这个概念,持久化也就是面对突发状况(比如断电)时候的对策,那么就是redo log来保证我们的持久化,他的思想核心就是二次落盘WAL,write ahead log ,也就是先写log,再根据log进行落盘。对于binlog,则是主从复制时候的作用了,这里便不再说了,所以mysql的大体内容就上边这些,也是常见的一些八股,有这么一个路线之后,你是否觉得好记忆了一点呢?
2025-07-18 15:30:34
553
原创 一文教会你雪花算法
1位来标识为正数,41位标识时间(这个待会细讲),5位标识不同的机房,5位标识不同的ID生成器(因为可能有时多台机器共同生成),12位标识单个ID生成器实例在同一毫秒生成的唯一ID。在面对一个新的概念的时候,我们要了解为什么要用这个东西,这个概念是什么,以及如何实现这个东西。所以我们来看看他是怎么解决上边四个问题的:对于1,使用时间解决,对于2,同样用时间,对于3 ,bigint类型的数字,一个占64位,可以接受 , 对于4,用其他冗余位来表示。OK啊,理论讲完了,下面我们来写一个简单的demo看一看。
2025-07-15 18:03:11
578
原创 如何看源码?
就跟写数学题差不多,你没有对应的解题思路,想死你也写不出来。你应该做的是有对应的思路,然后再去练习。如果你看不懂这个builder是怎么创建对象的,不妨先去看看书,这样你对builder的使用场景,实现方法都有了个基本的理解,看后去看代码是不是就很好理解了。我们经常会去看源码,无论是为了学习好的代码的编写方法,还是去对应的找bug,都需要对它的实现有所了解。但是源码的东西非常之多,太多的内容会对我们的理解造成很大的影响,并且看着看着就不想看了,效率非常低下。吧,多看多练多思考,想想有没有什么更好的写法。
2025-07-04 11:39:17
556
原创 如何一步一步通过debug和相关输出找到我想要的内容的-mcp client的自动配置过程是什么
那么拿想要的信息的核心:debug,输出日志,栈帧。这里定位到mcpToolCallbacks,它需要synMcpClients这个东西,这个东西那肯定也是bean了,当前时刻还没有创建这个bean,所以你再摁f8就去到了 synMcpClient这个bean的创建,也就是核心的Client的配置代码。前两个一个自动注入,一个通过配置文件寻找,这个直接点进那个类然后debug就可以了,最重要的是第三个参数,这个比较难搞,但是它有个record类型的类,那么直接debug然后一步一步调试就完事了。
2025-07-02 12:00:41
878
原创 如何快速定位bug
我们会遇到很多bug,所有debug的能力就显得尤为重要,而debug的思路往往取决于你debug时候的思路是什么,希望大家在日常debug的时候可以多思考,多总结,bug是无穷无尽的,但是思路是想通的,如果还有什么其他的好的方法,欢迎评论!又有句老话说的好,太少的信息和太多的信息都对我们的判断有影响。3. log日志,那么最常用的,也是最重要的对信息的查看就是日志了,java里常见的日志组件有lombok等,它的功能非常强大,比如log日志文件导出,比如根据不同的等级来显示不同的信息。
2025-06-30 14:14:54
446
原创 定时任务与解耦
2. 有关实现的优化的这种思考,就非常困难了(不仅仅要想思路,还要写代码),但是这里也提供了一种思路:当你因为将各种功能杂糅在一起的时候,不妨将他们分开看看。3. 最后视频中关于并发的使用是非常好的练习,我正苦恼于如何练习并发的时候看到了up的视频,虽然看一个20min的视频可能要我想一个小时,但是收获很多,希望up持续更下去。所以我们为什么不开两个线程,A用于执行任务,B用于执行计时,每个只专注于一件事,之后通过比如优先队列(堆),时间轮等算法将 A与B结合起来,B到时间后触发A执行任务。
2025-06-05 21:42:55
335
原创 JUC:虚假唤醒(spurious wakeup)
2. 同时将多个进程进行唤醒,比如notifyAll() method,如果有多个处于wait()的线程被唤醒,那么有可能其中一个通过cpu调度先执行,修改状态。如果使用if,那么其他线程都会逃逸出去(相当于虚假唤醒),而如果使用while对状态再次检测,其他线程就不会逃逸出去,就会再次进入wait。if 块内的语句执行不再受if判断的约束,但是while 块内的语句执行仍然会受while 条件判断的影响。时,我们应该用while而非if来实现对该状态的判断。
2025-06-03 22:06:02
227
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅