首先,造成这个问题的 BUG RocketMQ 官方已经在 3月16号 的这个提交中修复了,这里只是探讨一下在修复之前造成问题的具体细节,更多的上下文可以参考我之前写的 《RocketMQ Consumer 启动时都干了些啥?》 ,这篇文章讲解了 RocketMQ 的 Consumer 启动之后都做了哪些操作,对理解本次要讲解的 BUG 有一定的帮助。
其中讲到了:

重复消费自不必说,你 ClientID 都相同了。本篇着重聊聊为什么会消息堆积。
首先,造成这个问题的 BUG RocketMQ 官方已经在 3月16号 的这个提交中修复了,这里只是探讨一下在修复之前造成问题的具体细节,更多的上下文可以参考我之前写的 《RocketMQ Consumer 启动时都干了些啥?》 ,这篇文章讲解了 RocketMQ 的 Consumer 启动之后都做了哪些操作,对理解本次要讲解的 BUG 有一定的帮助。
其中讲到了:
重复消费自不必说,你 ClientID 都相同了。本篇着重聊聊为什么会消息堆积。
可能我们对 RocketMQ 的消费者认知乍一想很简单,就是一个拿来消费消息的客户端而已,你只需要指定对应的 Topic 和 ConsumerGroup,剩下的就是只需要:
就完事了。
当然,可能在实际业务场景下,确实是这样。但是如果我们不清楚 Consumer 启动之后到底会做些什么,底层的实现的一些细节,在面对复杂业务场景时,排查起来就会如同大海捞针般迷茫。
继续阅读之前讲了「从输入 URL 再到浏览器成功看到界面」中的域名是如何变成 IP 地址的,了解了 DNS 相关的东西。这篇文章就聊聊发生在 DNS 解析之后的操作——建立连接。也就是我们常说的三次握手。
看到三次握手你可能会说,这不是面试都被问烂了的题吗?
三次握手不就是:
CLOSE
状态,然后监听某个端口,此时服务器会进入 LISTEN
状态CLOSE
状态,客户端会向服务器发送一个带 SYN
标志位的数据包,主动发起连接。此时客户端会变成 SYN-SENT
状态SYN
和 ACK
,此时服务器的状态变为了 SYN-RCVD
ESTABLISH
ESTABLISH
可能大家都知道或者被问过一个问题,那就是很经典的「从浏览器输入 URL 再到页面展示,都发生了什么」。这个问题虽然简单,但是真的能够从回答的各种细节上看出不同人之间的水平差距。
这篇文章主要是聊一聊输入 URL 之后的第一步——域名解析
域名就类似于 http://www.google.com,而通过 ping
命令,就可以查询到对应域名的 IP 地址了。
那为什么又要有域名,又要有 IP 呢?
继续阅读Base64 是什么?是将字节流转换成可打印字符、将可打印字符转换为字节流的一种算法。Base64 使用 64 个可打印字符来表示转换后的数据。
准确的来说,Base64 不算是一种加、解密的算法,它是一种编码、解码的算法。这也是为什么我的用词是编码、解码,而不是加密、解密。
这里的讨论的前提是使用 UTF-8 编码
Base64 算法的原理,是将输入流中的字节按每 3 个分为一组,然后每次取 6 个比特,将其转换成表格中对应的数据,一直重复到没有剩余的字符为止,转换表格如下:
由于 MySQL 的整个体系太过于庞大,文章的篇幅有限,不能够完全的覆盖所有的方面。所以我会尽可能的从更加贴进我们日常使用的方式来进行解释。
首先,对于我们来说,MySQL 是个啥?我们从一个最简单的例子来回顾一下。
这可能就是最开始大家认知中的 MySQL。那 MySQL 中是怎么处理这个查询语句的呢?换句话说,它是如何感知到这串字符串是一个查询语句的?它是如何感知到该去哪张表中取数据?它是如何感知到该如何取数据?
到目前为止,都不知道。接下来我们一步一补来进行解析。
首先,要去 MySQL 执行命令,肯定是需要连接上 MySQL 服务器的,就像我们通过「用户名」和「密码」登陆网站一样。所以,我们首先要认识的就是连接池。
这种池化技术的作用很明显,复用连接,避免频繁的销毁、创建线程所带来的开销。除此之外,在这一层还可以根据你的账号密码对用户的合法性、用户的权限进行校验。
每一个连接都对应一个线程,「服务器」 和 「MySQL」 都一样,服务器的一个线程从服务器的连接池中取出一个连接,发起查询语句。MySQL 服务器的线程从连接池中取出一个线程,继续后续的流程。
那么后面的流程是啥呢?当然是分析 SQL 语句了。
继续阅读不知道大家有没有想过下面这件事?
我们平时调用
DELETE
在 MySQL 中删除的数据都去哪儿了?
这还用问吗?当然是被删除了啊
那么这里又有个新的问题了,如果在 InnoDB 下,多事务并发的情况下,如果事务A删除了 id=1
的数据,同时事务B又去读取 id=1
的数据,如果这条数据真的被删除了,那 MVCC 拿啥数据返回给用户呢?
没错,这就需要了解一下 MySQL 的多版本并发的原理相关的东西,感兴趣的可以去看我之前写的[这篇文章]()。
所以,实际情况中,调用了 DELETE
语句删除的数据并不会真正的被物理删除,这条数据其实还在那,只不过被打上了一个标记,标记已删除。
之前的文章简单的介绍了 MySQL 的事务隔离级别,它们分别是:读未提交、读已提交、可重复读、串行化。这篇文章我们就来探索一下 MySQL 事务隔离级别的底层原理。
本篇文章针对 InnoDB 存储引擎
我们知道,读未提交会造成脏读、幻读、不可重复读,读已提交会造成幻读、不可重复读,可重复读可能会有幻读,和串行化就不会有这些问题。
那 InnoDB 到底是怎么解决这些问题的呢?又或者,你有没有想过造成脏读、幻读、不可重复读的底层最根本的原因是什么呢?
这就是今天要聊的主角——MVCC(Multi-Version Concurrent Controll),也叫多版本并发控制。InnoDB 是一个支持多事务并发的存储引擎,它能让数据库中的读-写操作能够并发的进行,避免由于加锁而导致读阻塞。
正是由于有了 MVCC,在事务B更新 id=1
的数据时,事务A读取 id=1
的操作才不会被阻塞。而不阻塞的背后则是不加锁的一致性读。那什么是一致性读?
之前发过一篇文章,简单了解 MySQL 中相关的锁,里面提到了,如果我们使用的 MySQL 存储引擎为 InnoDB
,并且其事务隔离级别是 RR
可重复读的话,是可以避免幻读的。
但是没想到,都 1202
年了都还有人杠,说 InnoDB 的 RR 隔离级别下会出现幻读,只能依靠 gap 和 next-key 这两个锁来防止幻读
,最开始我还以为是他真的不知道这个点,就跟他聊,最后聊下来发现,发现是在钻牛角尖。
这个在下面讲到 可重复读 的隔离级别时会讲。
本来我觉得事务隔离级别这玩意儿太简单没啥可讲的,但是经过了上面这件事,我打算详细的把事务隔离给讲讲。接下来顺便就把 InnoDB
所有的事务隔离级别给搂一遍。
在聊事务隔离级别之前,我们需要知道 ACID 模型。
分别代表:
继续阅读对于 ArrayList
来说,我们平常用的最多的方法应该就是 add
和 remove
了,本文就主要通过这两个基础的方法入手,通过源码来看看 ArrayList
的底层原理。
这个应该是平常用的最多的方法了,其用法如下。
接下来我们就来看看 add
方法的底层源码。
ensureCapacityInternal
作用为:保证在不停的往 ArrayList 插入数据时,数组不会越界,并且实现自动扩容。