自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

fangmeng1997的博客

每天进步一点点

  • 博客(90)
  • 收藏
  • 关注

原创 坚持

凡人做一事,便须全副精神注在此一事,首尾不懈,不可见异思迁,做这样,想那样,坐这山,望那山。人而无恒,终身一无所成。 ——曾国藩

2020-09-09 22:15:54 153

原创 自我能力提升RoadMap一二三

自我能力提升RoadMap

2022-06-19 17:00:51 244

原创 从0到1设计分布式海量小文件存储系统

从0到1设计分布式海量小文件存储系统

2022-06-14 05:23:03 427

原创 从0到1设计分布式微服务注册中心

从0到1设计分布式微服务注册中心

2022-06-14 05:19:17 212

原创 从0到1设计高并发秒杀系统

从0到1设计高并发秒杀系统

2022-06-14 05:12:15 113

原创 源码阅读的意义:技术功底、hold住全场、设计能力、职场竞争

首先明确一件事情,源码,不是谁想读就可以读的。行业里,读过一些源码的,可能就10%~20%,但是大多数仅仅停留在了解点源码和原理的程度。有能力自主透彻阅读源码,深入吃透源码,化为自己的技术功底,而且运用到自己的项目里的,不足1%。所以源码实际上是码农技术水平的分水岭。那么阅读和分析源码的意义在哪儿?当你阅读了一个技术的源码之后,你的技术功底会得到大幅度的提升。比如说spring cloud,你阅读了spring cloud的源码之后,你对微服务技术架构的底层原理、架构设计、核心思想都了如指掌了,那么以后如果

2022-06-14 04:23:56 1658

原创 从0到1设计高性能网关

自研高性能网关-架构设计

2022-02-07 14:15:15 649

原创 可重入锁ReentrantLock源码分析

# 什么是可重入锁可重入锁是指一个线程获得了锁之后仍然可以反复的加锁,不会出现自己阻塞自己的情况。# 锁类型ReentrantLock 分为公平锁和非公平锁,可以通过构造方法来指定具体类型:```java //默认非公平锁 public ReentrantLock() { sync = new NonfairSync(); } //公平锁 public ReentrantLock(boolean fair) { s

2020-10-07 02:40:32 153

原创 一道老生常谈的字符串对象创建问题

问题和结论老生常谈的一个问题,String s = new String(“abc”)创建了几个对象,String s = "abc"又是创建了几个对象?先说结论:String s = new String(“abc”)创建了1个或2个对象,String s = "abc"创建了一个或0个对象接下来我们探究一下String s = new String(“abc”) 和String s = "abc"创建过程的区别。String s = new String(“abc”)的创建过程系统先在字符

2020-10-03 17:46:42 263

原创 一条update语句在MySQL内部是如何执行的

一、Server层阶段:1、连接器:负责跟客户端建立连接、获取权限、维持和管理连接2、分析器:验证通过以后,分析器会对该语句分析, 判断是否语法有错误等。3、优化器:选择索引,生成执行计划。4、执行器:根据优化器生成的执行计划,调用存储引擎API执行SQL。二、InnoDB引擎层阶段:1、事务执行阶段进入InnoDB后引擎层,首先会判断该SQL涉及到的页是否存在于缓存中,如果不存在则从磁盘读取该行记录所在的数据页并加载到BP缓冲池。假设不存在,然后通过 B+Tree 读取到磁盘的索引

2020-10-01 03:03:40 546

原创 MySQL5.7 常见调优参数速查

max_connections:允许客户端并发连接的最大数量,默认值是151,一般将该参数设置为500-2000max_connect_errors:如果客户端尝试连接的错误数量超过这个参数设置的值,则服务器不再接受新的客户端连接。可以通过清空主机的缓存来解除服务器的这种阻止新连接的状态,通过FLUSH HOSTS或mysqladmin flush-hosts命令来清空缓存。这个参数的默认值是100,一般将该参数设置为100000。interactive_timeout:Mysql关闭交互连接前的等待时

2020-09-30 02:05:53 912

原创 leetcode136-只出现一次的数字

# 题目描述给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。**说明:**你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?# 解题思路如果没有时间复杂度和空间复杂度的限制,这道题有很多种解法,可能的解法有如下几种。- 使用集合存储数字。遍历数组中的每个数字,如果集合中没有该数字,则将该数字加入集合,如果集合中已经有该数字,则将该数字从集合中删除,最后剩下的数字就是只出现一次的数字。- 使用哈希表存储每个数字和该数字

2020-09-29 12:08:56 126

原创 剑指offer—两个链表的第一个公共节点

题目描述输入两个链表,找出它们的第一个公共节点。解题思路我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。这样,当它们相遇时,所指向的结点就是第一个公共结点。参考代码/** * Definition for singly-linked list. * pub

2020-09-28 04:20:02 92

原创 leetcode236-二叉树的最近公共祖先

题目描述给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。解题思路1、递归复杂度分析时间复杂度:O(N),其中N是二叉树的节点数。二叉树的所有节点有且只会被访问一次,因此时间复杂度为 O(N)。空间复杂度:O(N),其中 N 是二叉树的节点数。递归调用的栈深度取决于二叉树的高度,二叉树最坏情况下为一条链,此时高度为 N,因此空间复杂度为 O(N)。2、存储父节点我们可以用哈希表存储所有节点的父节点,然后我们就可以利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访

2020-09-25 02:34:01 178 1

原创 深入理解RPC—健康检测

为什么要有健康检测?因为有了集群,所以每次发请求前,RPC 框架会根据路由和负载均衡算法选择一个具体的IP 地址。为了保证请求成功,我们就需要确保每次选择出来的 IP 对应的连接是健康的,这个逻辑你应该理解。但你也知道,调用方跟服务集群节点之间的网络状况是瞬息万变的,两者之间可能会出现闪断或者网络设备损坏等情况,那怎么保证选择出来的连接一定是可用的呢?从我的角度看,终极的解决方案是让调用方实时感知到节点的状态变化,这样他们才能做出正确的选择。这个道理像我们开车一样,车有各种各样的零件,我们不可能在开车

2020-09-24 16:17:34 1974 1

原创 深入理解RPC—架构设计

RPC 架构说起架构设计,我相信你一定不陌生。我理解的架构设计呢,就是从顶层角度出发,厘清各模块组件之间数据交互的流程,让我们对系统有一个整体的宏观认识。我们先看看 RPC 里面都有哪些功能模块。我们讲过,RPC 本质上就是一个远程调用,那肯定就需要通过网络来传输数据。虽然传输协议可以有多种选择,但考虑到可靠性的话,我们一般默认采用 TCP 协议。为了屏蔽网络传输的复杂性,我们需要封装一个单独的数据传输模块用来收发二进制数据,这个单独模块我们可以叫做传输模块。用户请求的时候是基于方法调用,方法出入参数

2020-09-21 21:18:23 998

原创 深入理解RPC—动态代理

动态代理如果我问你,你知道动态代理吗? 你可能会如数家珍般地告诉我动态代理的作用以及好处。那我现在接着问你,你在项目中用过动态代理吗?这时候可能有些人就会犹豫了。那我再换一个方式问你,你在项目中有实现过统一拦截的功能吗?比如授权认证、性能统计等等。你可能立马就会想到,我实现过呀,并且我知道可以用 Spring 的AOP 功能来实现。没错,进一步再想,在 Spring AOP 里面我们是怎么实现统一拦截的效果呢?并且是在我们不需要改动原有代码的前提下,还能实现非业务逻辑跟业务逻辑的解耦。这里的核心就是采用

2020-09-21 13:04:57 2468 2

原创 深入理解RPC—网络IO

网络通信和RPC首先我们知道RPC 是解决进程间通信的一种方式。一次 RPC 调用,本质就是服务消费者与服务提供者间的一次网络信息交换的过程。服务调用者通过网络 IO 发送一条请求消息,服务提供者接收并解析,处理完相关的业务逻辑之后,再发送一条响应消息给服务调用者,服务调用者接收并解析响应消息,处理完相关的响应逻辑,一次 RPC 调用便结束了。可以说,网络通信是整个 RPC 调用流程的基础。常见的网络 IO 模型那说到网络通信,就不得不提一下网络 IO 模型。为什么要讲网络 IO 模型呢?因为所谓的两

2020-09-20 02:47:05 1449

原创 深入理解RPC—序列化

为什么需要序列化?首先,我们得知道什么是序列化与反序列化。我们先回顾下RPC通信的流程:网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。对象是不能直接在网络中传输的,所以我们需要提前把它转成可传输的二进制,并且要求转换算法是可逆的,这个过程我们一般叫做“序列化”。这时,服务提供方就可以正确地从二进制数据中分割出不同的请求,同时根据请求类型和序列化类型,把二进制的消息体逆向还原成请求对象,这个过程我们称之为“反序列化”。这两个过程如下图所示:总结来说,序列化就是将对象转换成二进

2020-09-18 16:38:22 6107 3

原创 深入理解RPC—协议

协议一提到协议,你最先想到的可能是 TCP 协议、UDP 协议等等,并且这些网络传输协议的实现有点晦涩难懂。虽然在 RPC 中我们也会用到这些协议,但这些协议更多的是对我们上层应用是透明的,我们 RPC 在使用过程中并不太需要关注他们的细节。那RPC 协议到底是什么呢?可能我举个例子,你立马就明白了。HTTP 协议是不是很熟悉(本博客里面所说的 HTTP 默认都是 1.X)? 这应该是我们日常工作中用得最频繁的协议了,每天打开浏览器浏览的网页就是使用的 HTTP 协议。那 HTTP 协议跟 RPC 协议

2020-09-18 14:04:31 2587 1

原创 深入理解RPC—核心原理

什么是 RPC?RPC 的全称是 Remote Procedure Call,即远程过程调用。简单解读字面上的意思,远程肯定是指要跨机器而非本机,所以需要用到网络编程才能实现,但是不是只要通过网络通信访问到另一台机器的应用程序,就可以称之为 RPC 调用了?显然并不够。我理解的 RPC 是帮助我们屏蔽网络编程细节,实现调用远程方法就跟调用本地一样的体验,我们不需要因为这个方法是远程调用就需要编写很多与业务无关的代码。这就好比建在小河上的桥一样连接着河的两岸,如果没有小桥,我们需要通过划船、绕道等其他方

2020-09-17 11:31:20 1845 2

原创 leetcode141-判断链表是否有环

题目描述判断给定的链表中是否有环解题思路1、借助哈希表我们可以通过检查一个结点此前是否被访问过来判断链表是否为环形链表。常用的方法是使用哈希表。我们遍历所有结点并在哈希表中存储每个结点的引用。如果当前结点为空结点 null(即已检测到链表尾部的下一个结点),那么我们已经遍历完整个链表,并且该链表不是环形链表。如果当前结点的引用已经存在于哈希表中,那么返回 true(即该链表为环形链表)。2、双指针法想象一下,两名运动员以不同的速度在环形赛道上跑步会发生什么?通过使用具有不同速度的快、慢两个指

2020-09-15 09:28:45 209

原创 C10K问题—高并发网络IO模型

C10K 问题随着互联网的蓬勃发展,一个非常重要的问题摆在计算机工业界面前。这个问题就是如何使用最低的成本满足高性能和高并发的需求。这个问题在过去可能不是一个严重的问题,但是在 2000 年前后,互联网用户的人数井喷,如果说之前单机服务的用户数量还保持在一个比较低的水平,比如说只有上百个用户,那么在互联网逐渐普及的情况下,服务于成千上万个用户就将是非常普遍的情形,在这种情形下,如果还按照之前单机的玩法,成本就将超过人们想象,只有超级有钱的大玩家才可以继续下去。于是,C10K 问题应运而生。C10K 问题

2020-09-14 13:14:00 483

原创 剑指offer—树的子结构

题目描述输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)解题思路1)先对A树进行遍历,找到与B树的根结点值相同的结点R;2)判断A树中以R为根结点的子树是否包含B树一样的结构。参考代码public class Solution{ public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null;

2020-09-14 00:50:14 73

原创 剑指offer—合并两个排序的链表

题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。解题思路递归实现:合并过程中,每次都是从两个链表中找出较小的一个来链接,因此可以采用递归来实现:当任意一个链表为null时,直接链接另一个链表即可;其余情况只需要在两个链表中找出较小的一个结点进行链接,该结点的next值继续通过递归函数来链接。非递归实现:非递归实现比较容易想到,直接进行分情况讨论即可,要稍微注意下后面代码中头结点的赋值过程。参考代码//题目:输入两个递增排序的链表,合并这两个链表

2020-09-13 01:24:20 126

原创 Kafka集群原理

Kafka 是一个分布式的、可水平扩展的、基于发布/订阅模式的、支持容错的消息系统。一、集群成员Kafka 使用 Zookeeper 来维护集群成员的信息。每个 broker 都有一个唯一标识符,这个标识符可以在配置文件里指定,也可以自动生成。在 broker 启动的时候,它通过创建临时节点把自己的 ID 注册到 Zookeeper。Kafka 组件订阅 Zookeeper 的 /broker/ids 路径,当有 broker 加入集群或退出集群时,这些组件就可以获得通知。ZooKeeper 两.

2020-09-12 18:31:59 8223

原创 Kafka重平衡机制

一、什么是 Rebalance分区的所有权从一个消费者转移到另一个消费者,这样的行为被称为重平衡(Rebalance)。Rebalance 实现了消费者群组的高可用性和伸缩性。消费者通过向被指派为群组协调器(Coordinator)的 broker 发送心跳来维持它们和群组的从属关系以及它们对分区的所有权。所谓协调者,在 Kafka 中对应的术语是 Coordinator,它专门为 Consumer Group 服务,负责为 Group 执行 Rebalance 以及提供位移管理和组成员管理等。具体

2020-09-12 10:51:51 2477

原创 Kafka高性能读写原理

Kafka是高吞吐低延迟的高并发、高性能的消息中间件,在大数据领域有极为广泛的运用。配置良好的Kafka集群甚至可以做到每秒几十万、上百万的超高并发写入。那么Kafka到底是如何做到这么高的吞吐量和性能的呢?一、页缓存技术 + 磁盘顺序写首先Kafka每次接收到数据都会往磁盘上去写,如下图所示。那么在这里我们不禁有一个疑问了,如果把数据基于磁盘来存储,频繁的往磁盘文件里写数据,这个性能会不会很差?大家肯定都觉得磁盘写性能是极差的。没错,要是真的跟上面那个图那么简单的话,那确实这个性能是比较差的。.

2020-09-11 09:35:16 824

原创 Kafka可靠数据传递

一、 可靠性保证Kafka 到底在什么情况下才能保证消息不丢失呢?一句话概括,Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证。Kafka 的可靠性保证:Kafka 可以保证分区消息的顺序。只有当消息被写入分区的若干同步副本时,才被认为是已提交的。为什么是若干个 Broker 呢?这取决于你对“已提交”的定义。你可以选择只要 Leader 成功保存该消息就算是已提交,也可以是令所有 Broker 都成功保存该消息才算是已提交。只要还有一个副本是存活的,

2020-09-10 19:41:23 320

原创 Kafka副本机制理解

分布式系统中的副本机制所谓的副本机制(Replication),也可以称之为备份机制,通常是指分布式系统在多台网络互联的机器上保存有相同的数据拷贝。副本机制有什么好处呢?提供数据冗余。即使系统部分组件失效,系统依然能够继续运转,因而增加了整体可用性以及数据持久性。提供高伸缩性。支持横向扩展,能够通过增加机器的方式来提升读性能,进而提高读操作吞吐量。改善数据局部性。允许将数据放入与用户地理位置相近的地方,从而降低系统延时。这些优点都是在分布式系统教科书中最常被提及的,但是有些遗憾的是

2020-09-10 11:13:48 782

原创 剑指offer—链表中倒数第k个结点

题目描述输入一个链表,输出该链表中倒数第k个结点。解题思路经典的双指针法。定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1步,第二个指针保持不动,从第k步开始,第二个指针也开始从链表的头指针开始遍历,由于两个指针的距离保持在k-1,当第一个指针到达链表的尾节点时,第二个指针刚好指向倒数第k个节点。关注要点链表头指针是否为空,若为空则直接返回回null。k是否为0,k为0也就是要查找倒数第0个节点,由于计数一般是从1开始的,所有输入0没有实际意义,返回null。k是否超出链

2020-09-10 00:52:07 65

原创 Redis主从同步机制

Redis主从库和读写分离Redis 提供了主从库模式,以保证数据副本的一致,主从库之间采用的是读写分离的方式。读操作:主库、从库都可以接收;写操作:首先到主库执行,然后,主库将写操作同步给从库。为什么要采用读写分离的方式呢?你可以设想一下,如果在上图中,不管是主库还是从库,都能接收客户端的写操作,那么,一个直接的问题就是:如果客户端对同一个数据(例如 k1)前后修改了三次,每一次的修改请求都发送到不同的实例上,在不同的实例上执行,那么,这个数据在这三个实例上的副本就不一致了(分别是 v1、

2020-09-08 10:30:10 572

原创 ArrayList源码分析—基于JDK8

# ArrayList概述1. ArrayList 是一种变长的集合类,基于定长数组实现。2. ArrayList 允许空值和重复元素,当往 ArrayList 中添加的元素数量大于其底层数组容量时,其会通过扩容机制重新生成一个更大的数组。3. 由于 ArrayList 底层基于数组实现,所以其可以保证在 O(1) 复杂度下完成随机查找操作。4. ArrayList 是非线程安全类,并发环境下,多个线程同时操作 ArrayList,会引发不可预知的异常或错误。

2020-09-04 13:23:48 111

原创 Redis高性能IO模型

Redis是单线程的吗首先,要厘清一个事实,我们通常说,Redis 是单线程,主要是指 Redis 的网络 IO和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。所以,严格来说,Redis 并不是单线程,但是我们一般把 Redis 称为单线程高性能,这样显得“酷”些。接下来,我也会把 Redis 称为单线程模式。而且,这也会促使你紧接着提问:“为什么用单线程?为什么单线程能这么

2020-09-03 15:34:51 216

原创 MySQL日志系统原理

Undo LogUndo Log介绍Undo:意为撤销或取消,以撤销操作为目的,返回指定某个状态的操作。Undo Log:数据库事务开始之前,会将要修改的记录存放到 Undo 日志里,当事务回滚时或者数据库崩溃时,可以利用 Undo 日志,撤销未提交事务对数据库产生的影响。Undo Log产生和销毁:Undo Log在事务开始前产生;事务在提交时,并不会立刻删除undo log,innodb会将该事务对应的undo log放入到删除列表中,后面会通过后台线程purge thread进行回收处理。Un

2020-08-29 01:05:47 691

原创 累加器LongAccumulator用法—基于JDK8

Adder我们要知道 Adder 和 Accumulator 都是 Java 8 引入的,是相对比较新的类。对于 Adder 而言,比如最典型的 LongAdder,在高并发下 LongAdder 比 AtomicLong 效率更高,因为对于 AtomicLong 而言,它只适合用于低并发场景,否则在高并发的场景下,由于 CAS 的冲突概率大,会导致经常自旋,影响整体效率。而 LongAdder 引入了分段锁的概念,当竞争不激烈的时候,所有线程都是通过 CAS 对同一个 Base 变量进行修改,但是当竞

2020-08-24 20:53:35 1695 1

原创 AtomicInteger原子操作分析

原子类在编程领域里,原子性意味着“一组操作要么全都操作成功,要么全都失败,不能只操作成功其中的一部分”。而 java.util.concurrent.atomic 下的类,就是具有原子性的类,可以原子性地执行添加、递增、递减等操作。比如之前多线程下的线程不安全的 i++ 问题,到了原子类这里,就可以用功能相同且线程安全的 getAndIncrement 方法来优雅地解决。原子类的作用和锁有类似之处,是为了保证并发情况下线程安全。不过原子类相比于锁,有一定的优势:粒度更细:原子变量可以把竞争范围缩小到

2020-08-24 12:17:23 460

原创 延迟队列DelayQueue用法

DelayQueue介绍我们首先介绍一下DelayQueue,DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的Delayed 元素。DelayQueue使用场景和用法DelayQueue阻塞队列在我们系统开发中也常常会用到,例如:缓存系统的设计,缓存中的对象,超过了空闲时间,需要从缓存中移出;任务调度系统,能够准确的把握任务的执行时间。我们可能需要通过线程处理很多时间上要求很严格的数据,如果使用普通的线程,我们就需要遍历所有的对象,一个一

2020-08-21 20:32:02 690

原创 阻塞队列介绍以及在线程池中的应用

> BlockingQueue 接口的实现类都被放在了 J.U.C 包中,包括ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue,以及DelayQueue。# 阻塞队列介绍## ArrayBlockingQueue先从最基础的 ArrayBlockingQueue 说起。ArrayBlockingQueue 是最典型的有界队列,其内部是用数组存储元素的,利用 ReentrantLock 实现线

2020-08-21 17:43:13 301

原创 CopyOnWriteArrayList源码分析

CopyOnWriteArrayListJDK1.5 开始,Java 并发包里提供了使用 CopyOnWrite 机制实现的并发容器CopyOnWriteArrayList 作为主要的并发 List,CopyOnWrite 的并发集合还包括 CopyOnWriteArraySet,其底层也是利用 CopyOnWriteArrayList 实现的。适用场景读操作可以尽可能的快,而写即使慢一些也没关系在很多应用场景中,读操作可能会远远多于写操作。比如,有些系统级别的信息,往往只需要加载或者修改很少的

2020-08-20 22:56:24 149

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除