- 博客(33)
- 收藏
- 关注
原创 Redis的使用(五)常见使用场景-分布式锁实现原理
为了解决并发问题,我们可以通过加锁的方式来保证数据的一致性,比如java中的synchronize关键字或者ReentrantLock,但是他们只能在同一jvm进程上加锁。现在的项目基本上都是分布式系统,如何对多个java实例进行加锁,这就需要用到分布式锁。分布式锁可以由多种实现方式,本文将要介绍的就是采用redis实现的方式。
2024-07-19 01:25:31
946
1
原创 redis原理之底层数据结构(四)-字典
字典是一个由两个hash表组成的数据结构,hash表其实就是类似java的hashTable,所以hashTable是由多个hash entry组成。为什么字典是由两个hash表组成呢,它的数据结构是怎样的呢?我们后面将会讨论。
2024-07-17 22:32:57
173
原创 redis原理之底层数据结构(三)-quicklist
前面讲过的ziplist在查找元素的时候是o(n)的复杂度,如果ziplist长度太长,会导致查找元素很缓慢,而ziplist是拥有内存连续的优势,为了保留ziplist内存连续的优势,但是又不能保留太长的长度,我们出现了quicklist,quicklist其实就是将多个ziplist通过指针链接成一个双端链表。
2024-07-16 22:03:37
488
1
原创 redis原理之底层数据结构(二)-压缩列表
压缩列表是redis最底层的结构之一,比如redis中的hash,list在某些场景下使用的都是压缩列表。接下来就让我们看看压缩列表结构究竟是怎样的。
2024-07-15 21:12:45
653
1
原创 Redis的使用(四)常见使用场景-缓存使用技巧
缓存穿透就是,当客户端访问缓存时,发现缓存中没有数据,然后去访问数据库,但是数据库中也没有数据。所以在读取数据的时候,因为数据库中没有数据给redis缓存,所以请求会一直到数据库中,导致数据库压力过大。缓存雪崩就是在某一个时刻大量的key同时过期或者redis直接宕机,导致大量请求涌入到数据库,数据库压力激增。缓存击穿就是在高并发场景下,因为热点key(这里热点key可以指访问频率高或者重建缓存时间长的key)过期,导致大量线程同时重建缓存。
2024-07-12 22:23:43
796
1
原创 redis原理之底层数据结构(一)-动态字符串sds
可以看出redis的sds其实就相当于java中的ArrayList,都具有动态扩容,缩容等功能。
2024-07-11 20:27:59
566
3
原创 Redis的使用(三)常见使用场景-session共享
传统方式是在用户登录过后,用户会校验登录是否成功,如果登录成功,会将用户信息保存到session中,后面用户再次访问的时候,会通过cookie的方式将用户的sessionid携带过来,如果用户在session中根据sessionId查询到用户信息,便表示当前用户已经登录过。1.用于用户信息是存储在session中的,而session是属于一个Tomcat实例,如果采用分布式部署的话,当请求到tomcat1的话,保存到tomcat1的话,下次登录请求到tomcat2的话,便查询不到用户信息。
2024-07-09 23:07:27
1143
1
原创 Redis的使用(二)redis的命令总结
这一小节,我们主要来研究一下redis的五大类型的基本使用,数据类型如下:redis我们接下来看一看这八种类型的基本使用。,同时我们也可以用help 数据类型查看命令的帮助文档。
2024-07-02 20:19:32
262
4
原创 Redis的使用(一)概述
本文主要介绍了redis的一些特点和作用,并且和Memcached进行了对比,后面我们将来探讨redis的具体使用以及每个高级特性是如何实现的。
2024-07-01 20:02:40
537
4
原创 深度解析RocketMq源码-消息推送、持久化、消费全流程
至此,消费者从产生到存储,再到消费的怎个逻辑我们应该是很清晰了。在生产端,生产者根据负载均衡策略(比如轮询或者一致性hash等)选择对应的messagequeue所在的broker中,然后通过Netty,将消费发送broker去;broker收到消息过后,会直接将消息持久化到commitLog中,然后再单独的启动一个线程,根据持久化的commitLog建立IndexFile和consumequeue,并且会唤醒因为长轮询阻塞的消费线程,通过Netty将消发送到consume中;
2024-06-30 00:30:07
1579
3
原创 深度解析RocketMq源码-消费者索引ConsumeQueue
至此,我们已经大概了解消息在进入到broker过后做了什么。在生产者推送消息到broker过后,为了保证数据的能够快速的持久化,是直接按照到达顺序写入到commitLog中的,然后就会给主线程返回生产消息成功的通知。但是消费者需要根据topic和queueId获取到一条消息,并且需要根据消息的key检索一条消息。为了满足上述两个需求,rocketmq会启动一个线程,扫描commitLog,如果有新的消息写入,便会构建IndexFile和consumequeue两个文件,其实相当于两个索引文件。
2024-06-28 21:49:00
1156
3
原创 深度解析RocketMq源码-IndexFile
在工作中,我们经常需要根据msgKey查询到某条日志。但是,通过前面对commitLog分析,producer将消息推送到broker过后,其实broker是直接消息到达broker的先后顺序写入到commitLog中的。我们如果想根据msgKey检索一条消息无疑大海捞针,所以们需要像数集一样建立一个目录,我们其实可以想到的是构建一个Map,key存储msgKey,value存储msg在commitLog中的物理偏移量。而这个目录其实就是indexFile。
2024-06-27 23:24:05
890
4
原创 深度解析RocketMq源码-高可用存储组件(四)Dledger框架日志同步流程
在中讲过,raft协议中,日志同步主要有两个地方,一个是leader会跟follower同步数据,另一个是在新leader诞生的时候,会与以前的follower进行日志匹配,作一致性校验。而在Dledger的进行日志校验的组件就是DLedgerEntryPusher,接下来我们将探索该组件的源码。
2024-06-26 21:03:23
481
2
原创 深度解析RocketMq源码-高可用存储组件(三)Dledger框架选举流程
当超过一定时间follower未接收到leader的心跳包过后,便会更改自己的状态为candidate,并且开始选举。其实就是改变了自己的状态为candidate,并且调用RoleChangeHandler这个钩子函数,RoleChangeHandler其实是提供给客户端的一个钩子,客户端可以实现它来做角色变更后的一些后置处理。其实就是根据leader发送过来的心跳包做逻辑判断,如果自己没有leader,便更新自己的leader为心跳包中的leader。改变自己的角色为leader。
2024-06-25 20:37:34
544
1
原创 深度解析RocketMq源码-高可用存储组件(二)Dledger框架概览
本文主要讲的是Dledger框架的大概组成部分,已经每个组件的使用,后面会详细介绍Dledger的投票和日志同步流程。
2024-06-24 23:30:25
1034
1
原创 深度解析RocketMq源码-高可用存储组件(一) raft协议详解
term是一个单调递增的数字,每次candidate在发起选举的时候,便会将当前的term增加1。并且raft协议规定在每个term中,只能有一次选举。
2024-06-23 18:26:30
768
4
原创 深度解析RocketMq源码-高可用存储组件(一) raft协议详解
所以在leader宕机过后,一定能够保证整个集群超过一半的节点拥有最新的日志,再结合投票时一定是半数以上的支持,才能当选leader,也即他的索引一定是大于等于集群半数以上节点的,所以一定有用最新的日志。前面的文章已经分析过,以前rocketmq通过主从复制的思想实现系统的高可用,即在搭建集群的时候会手动的设置一个主节点和从节点,在写入数据的时候,会先写入到主broker,然后再同步到从节点中。term是一个单调递增的数字,每次candidate在发起选举的时候,便会将当前的term增加1。
2024-06-23 18:22:13
1066
原创 深度解析RocketMq源码-持久化组件(四) CommitLog
至此,rocketmq的核心持久化主键commitLog我们便已经全部分析完成,简单而言,commitLog持有一个messageFileQueue,而mappedFileQueue对应不同的mappedFile文件,而mappedFile通过mmap技术与磁盘中的文件建立映射。
2024-06-20 21:40:00
779
1
原创 深度解析RocketMq源码-持久化组件(三) 刷盘策略
同步刷盘主要是在发送刷盘请求过后,会同步等待刷盘结果,这是它不会丢数据的根本原因。异步刷盘有两种模式定时模式和实时模式。实时模式就是数据写入后立刻刷盘,但是调用线程并不会阻塞等待刷盘结果;定时模式就是会启动一个线程每过500ms写入数据,这样做可以增大一次刷盘的条数,减少磁盘IO。
2024-06-18 00:13:08
1130
1
原创 深度解析RocketMq源码-持久化组件(二) MappedFileQueue
在获取到最后一块mappedfile的时候,可以根据needcreate参数判断:如果超过内存范围,是否需要重新构建一个mappedfile。//重要,根据起始偏移量获取到最后一块mappedfile,并且根据needcreate参数判断如果超过内存范围,是否需要重新构建一个mappedfile//获取到mappedfilequeue中的最后一个mappedfile//如果最后一块mappedfile为空,表示此时为初始化,获取到新的mapperfile的起始位置。
2024-06-16 19:06:29
561
1
原创 深度解析RocketMq源码-持久化组件(一) MappedFile
mappedFile本质上是利用mapp技术来提高读写效率的,而mappedFile的核心本质上就是mappedFileBuffer,默认大小为1G,可以由mappedFileSizeCommitLog来进行控制。
2024-06-15 12:25:58
984
3
原创 RocketMq生产常见问题及解决方案(三) 顺序消息和消息堆积的解决法方式
而在订单业务常见的一个场景是,每个订单有下单->支付->发货这已操作,需要通过mq同步给第三方,我们在同步的时候需要保证每个单据内这三个操作是有序的就行,这就是局部有序消息。订阅关系不一致导致消息堆积,在rocketmq中,同一个消费者组,应该订阅的topic和tag信息应该是一模一样的,即消费者组在rocketmq中是作为一个基本单位存在的。我么有一次发生的问题就是,有一个灰度和非灰度环境,在配置的时候,灰度环境和非灰度环境都属于一个消费者组,但是消费的topic不一样,导致消费者不能消费。
2024-06-06 21:32:40
241
4
原创 RocketMq生产常见问题及解决方案(二) 重复消费产生原因以及解决方式
保证消息不被重复消费的主要解决方案主要是保证消费者端的幂等性。主要解决思路是更加messageId作为未Id,保证它的唯一性。所以我们可以用redis或者mysql的唯一索引来存储messageId,当消费的时候根据messageId查询一下redis或者mysql,如果查到有数据,表示已经被重复消费。在插入数据的时候我们也可以采用分布式锁防止并发插入问题。
2024-06-06 01:28:22
966
2
原创 RocketMq生产常见问题及解决方案(一) 如何保证消息不丢失
4.如果commit或者rollback消息发送失败,此时业务流程已经执行成功,mq会启动一个定时任务检查未被消费的half消息,并且回调业务方,判断这个half消息是应该回滚还是提交。答案是否定的,以保证消费者一定消费为例,当消息者一直没有消费成功的时候,rocketmq的消费者会进行重试,当超过16次过后,会加入到死信队列,这个时候,我们可以启动一个定时任务去扫描死信队列的内容,做对应的逻辑处理。将推送到mq消息和本地事务放到同一个事务中,并且如果失败,便多次重试,如果多次重试未果,便回滚事务。
2024-06-06 01:03:14
643
1
原创 深度解析RocketMq源码-Namesrv
前面几篇文章已经介绍了rocketmq的架构,如何使用以及生产上问题如何解决。接下来几篇文章将会介绍rocketmq的源码,我们在看问题的时候,会带着我们的问题去代码找答案,同时在代码中学习一些常见的代码技巧。接下来,我们先来探究一下NameSrv的源码。1.NameSrv之间是相互通信的吗?从上面源码分析,可以看出namesrv之间是没有通信的。2.NameSrv是如何存储topic的路由信息的?
2024-05-27 22:48:24
1189
3
原创 深度解析RocketMq源码-远程通信组件
rocketmq的各个组件之间的通信都是用rocketmq-remoting这个组件实现,而这个组件底层采用的是netty来进行通信的,所以学习这个组件我们可以学到netty的使用。在介绍这个组件之前,我们来了解一下什么是netty。NettyRemotingAbstract的主要作用是接收Netty的请求,根据请求找到一个响应或者请求的processor,然后调用对应的客户端实现的processor来处理结果。/***///oneway请求的信号量,通过它来控制同时发送oneway请求的并发数。
2024-05-24 00:36:46
753
2
原创 RocketMq架构以及基本使用
messageQueue是真正存储消息的地方,其实在rocketMq里面,消息是顺序存储到不同文本文件里面的,这些文本文件就是commitLog,并且在存储的时候,会针对里面不同的topic建立不同的索引,这些索引就是consumeQueue,所以消费者在消费的时候,是根据consumeQueue获取到自己在commitLog中的索引位置,然后找到真正需要消费的数据,所以这里consumeQueue其实就是messageQueue。比如秒杀场景,如果不引入消息中间件,可能让请求压力直接给到数据库。
2024-04-15 22:31:24
459
4
原创 JVM-java内存模型及java关键字内存语义
什么是java内存模型,就我理解,可以如上图所示。首先,因为java的内存模型是一个二级缓存,线程首先需要将数据写入到本地缓存,然后才能将本地缓存的数据刷到主内存中,所以就出现了可见性的和有序性的问题。由于cpu会进行优化,会进行cpu级别指令重排序。并且在java前端编译器中,也会对java代码进行优化,也有可能对代码进行重排序,这就导致了有序性问题。为了解决上述问题,jmm是怎么做的呢?jmm会禁用掉部分指令重排序。同时针对java的二级缓存带来的问题,java会在部分指令之间加入内存屏障。
2024-03-28 22:05:30
821
1
原创 JVM-类加载机制
符号引用其实就是字节码文件常量池里面名称标识,比如变量名,方法名等就是符号引用。直接引用就是变量或者方法的地址。在解析的时候其实就是将方法的名称,找到对应的存储地址,并且生成一条指令访问该地址。即数组不通过类加载器进行加载。java的类加载器主要是分成4类:1.启动类加载器:主要加载java核心库里面的类,比如rt.jat,是由c++实现的,如果要把代码交给启动类加载器加载,可以直接使用null便可;2.扩展类加载器:主要加载/lib/ext目录下面的文件;
2024-03-26 22:16:49
792
1
原创 JVM - java内存结构
在理解元空间和运行时常量池之前,我们有必要了解到java的类和对象究竟是如何在内存中存储的。众所周知,java是由C++写的,而在类加载的时候,其实就是将java字节码读入到了内存中。JVM解析字节码,并且生成一个Klass对象。Klass对象其实就是对一个java类的描述,可以看他的一些属性:_annotations:保存该类的所有注解;_java_fields_count:已声明的Java字段数量;_constants:保存该类的常量池指针......
2024-03-12 23:24:13
1093
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人