自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

一江溪水

hello word

  • 博客(106)
  • 资源 (1)
  • 收藏
  • 关注

原创 GO 中的 init 函数

go语言中有一个非常神奇的函数init,它可以在所有程序执行开始前被执行,并且每个package下面可以存在多个init函数,我们一起来看看这个奇怪的init函数。

2023-02-12 14:57:52 1929 1

原创 全链路追踪 jaeger

Jaeger是Uber开发并开源的一款分布式追踪系统,兼容分布式跟踪信息传递分布式事务监控问题分析服务依赖性分析性能优化。

2023-01-24 00:25:34 2050

原创 全链路追踪之OpenTracing

现在的大多数互联网服务,基本都是用复杂,大规模分布式集群来实现,微服务化,这些服务模块分布在不同的机器,不同的数据中心,由不同团队,语言开发而成。

2023-01-08 16:59:08 1063

原创 redis 事务

在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。可以监控一个或多个键,如果在事务执行之前,被监视的key被其他命令修改(或删除),则事务被打断(类似乐观锁),之后的事务就不会执行,监控一直持续到。可以保证脚本内的命令一次性、按顺序地执行,其同时也不提供事务运行错误的回滚,执行过程中如果部分命令运行错误,剩下的命令还是会继续运行完。是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。

2022-12-25 16:21:56 765

原创 http 库的服务端实现

上两篇文章介绍了 http 客户端的实现,这篇文章看一下服务端的实现服务端的代码看主逻辑主要是看两部分,一个是注册处理器,标准库使用map进行存储,本质是一个静态索引,同时维护了一个切片,用来做前缀匹配,只要以/结尾的,都会在切片中存储;

2022-12-24 17:21:16 1187 1

原创 net/http 库的客户端实现(下)

上一篇文章我们讲了net/http库客户端 request 的构建,接下来继续讲构建HTTP请求之后的处理操作

2022-12-24 16:06:40 911

原创 net/http 库的客户端实现(上)

Go语言标准库net/http是一个非常强大的标准库,使得构建HTTP请求和编写Web服务器的工作变得非常简单。我们来看看是他是如何实现客户端和服务端的。

2022-12-17 17:20:02 615

原创 OAuth2.0的四种授权方式

OAuth简单理解就是一种授权机制,它是在客户端和资源所有者之间的授权层,用来分离两种不同的角色。在资源所有者同意并向客户端颁发令牌后,客户端携带令牌可以访问资源所有者的资源。

2022-12-11 15:31:26 2531

原创 MQTT协议

MQTT是一种基于发布/订阅模式的轻量级通讯协议,通过订阅相应的主题来获取消息,是物联网(Internet of Thing)中的一个标准传输协议。该协议将消息的发布者(publisher)与订阅者(subscriber)进行分离,因此可以在不可靠的网络环境中,为远程连接的设备提供可靠的消息服务

2022-12-10 22:31:01 924

原创 gin 集成 Swagger

一个好的项目工程,必然离不开一个好的 API 文档,如果要自己编写 API 文档,维护起来比较困难,而且难以保证一致性,因此我们要自动生成在线接口文档。swagger 在 java 里面,是一个非常流行的 api 组件,他们维护了 go 版本 swaggo,可以通过 Swagger 2.0 自动生成RESTful API 文档。安装到 $PATH若 的 目录下面没有 文件,需要 若 没有加入 中,需要将其可执行文件移动到 下检查安装出现这

2022-12-04 15:47:51 832

原创 gin 统一响应结果

使用 gin 框架,编写 api 接口时,需要定义返回格式,这种方法有一个弊端,每次返回都需要写这个结构封装统一结果定义统一结构体使用这样在每个HandlerFunc 方法只需要使用 result 下面的方法即可,统一管理,还可以定义统一的错误码

2022-12-03 23:35:57 1276 1

原创 golang的new和make

string 的零值是"",int 的零值是0,引用类型的零值是nil。前面两种类型可以直接使用,但如果把它改成指针,就会报错

2022-11-26 23:49:52 420

原创 @Transactional注解为何会失效

使用 @Transactional 注解能保证方法内多个数据库操作要么同时成功、要么同时失败。但是有很多细节需要注意,不然@Transactional可能会失效。

2022-11-20 22:46:35 931

原创 声明式事务@Transactional

事务管理在 Web 系统开发中是非常重要的,可以在一定程度上保证数据的一致性。Spring提供了非常优秀的事务管理机制,主要分为编程式事务和声明式事务。

2022-11-19 20:46:43 509

原创 解决跨越的几种方式

域 的定义:协议 + 域名 + 端口。三者完全相同则为同域,反之有其一不同均为不同域,当前发起请求的 域 和请求指向的 域 属于不同域时,该次请求称之为跨域请求。

2022-11-13 13:59:07 724

原创 事件总线 EventBus

EventBus 顾名思义,事件总线,是一个轻量级的发布 - 订阅模式的应用模式。相比于 MQ 更加简洁,轻量,它可以在一个小系统模块内部使用EventBus允许组件之间通过发布 - 订阅进行通信,而不需要组件之间显示的注册。它专门设计为了代替使用显示注册的传统的 Java 进程内事件分发。它不是通用的发布-订阅系统,也不是用于进程间通信的。

2022-11-12 15:18:07 4189

原创 Golang 数据结构之 Slice (三)

前言Golang 数据结构之 Slice (二)上一篇文章介绍了一下扩容的基本情况,这一篇文章分析要 growslice 函数的源码源码我们看看 growslice函数的源码,可以分成三部分:func growslice(et *_type, old slice, cap int) slice { if raceenabled { callerpc := getcallerpc(unsafe.Pointer(&et)) racereadrangepc(old.array, uin

2022-05-08 15:36:14 479 1

原创 Golang 数据结构之 Slice (二)

前言Golang 数据结构之 Slice (一)上一篇文章写了Slice的基本数据结构,而且提到了Slice可以自动扩容,这篇文章就简单看看Slice是怎么样扩容的。append函数说扩容之前,不得不说一下 Slice 内置的 append 函数,这是一个用于向slice 追加元素的函数func main(){ var nums []int for i := 0; i < 10; i++ { nums = append(nums, i) } fmt.Printf("nu

2022-05-07 22:12:13 482

原创 Golang 数据结构之 Slice (一)

Golang 数据结构之 Slice前言Slice(切片)是抽象在 Array(数组)之上的特殊的数据类型类型,在了解slice之前需要先了解一下Array的情况。Array 数组Array数组就是 Golang 的基本数据类型中的数字,是一种顺序存储结构。用法func main() { nums := [4]int{} nums[0] = 1 nums[2] = 3 fmt.Printf("nums: %v\n", nums) fmt.Printf("nums[2]: %d\n",

2022-05-04 22:21:49 1104

原创 什么是自旋锁

前言阻塞或唤醒一个Java线程需要操作系统切换CPU状态来完成,这种状态转换需要耗费处理器时间。如果同步代码块中的内容过于简单,状态转换消耗的时间有可能比用户代码执行的时间还要长。自旋锁在有些场景中,同步资源的锁定时间很短,为了这一小段时间去切换线程,线程挂起和恢复现场的花费可能会让系统得不偿失。如果机器有多个CPU核心,能够让两个或以上的线程同时并行执行,我们就可以让后面那个请求锁的线程不放弃CPU的执行时间,看看持有锁的线程是否很快就会释放锁。为了让当前线程“稍等一下”,我们需让当前线程进行自

2022-01-02 21:28:58 10795

原创 悲观锁 VS 乐观锁

前言Java中有很多锁,每种锁因其特性的不同,在适当的场景下的效率也有很大的差别。今天我们对比一下乐观锁和悲观锁,看看他们有什么不同和相同。乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有比较广泛的应用。悲观锁对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。悲观锁调用方式分别是 synchr

2021-12-26 15:01:18 338

原创 JDK的锁升级过程

2021-12-25 22:56:05 359

原创 Redis为什么这么快?

Redis经常被用作做缓存, 一致性要求不高的场景,还可以当做kv存储使用。另外, Redis还提供了消息订阅、事务、索引等特性。我们还可以利用集群特性搭建分布式存储服务,实现非强一致性的分布式锁服务。Redis用到上述场景, 都有一个共同的优势, 就是处理速度快(高性能)。...

2021-12-04 19:59:00 3718

原创 Redis分布式锁如何自动续期

Redis 实现分布式锁指定一个 key 作为锁标记,存入 Redis 中,指定一个 唯一的用户标识作为 value。当 key 不存在时才能设置值,确保同一时间只有一个客户端进程获得锁,满足互斥性特性。设置一个过期时间,防止因系统异常导致没能删除这个 key,满足防死锁特性。当处理完业务之后需要清除这个 key 来释放锁,清除 key 时需要校验 value 值,需要满足只有加锁的人才能释放锁 。问题如果这个锁的过期时间是30秒,但是业务运行超过了30秒,比如40秒,当业务运行到30秒的时

2021-11-27 16:33:38 4893

原创 Spring Boot是如何实现自动装配的

什么是自动装配?自动装配就是通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能。Spring Boot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 Spring Boot 定义的标准,就能将自己的功能装置进 Spring Boot。在Spring Boot

2021-11-21 17:56:22 3944 1

原创 一致性哈希算法

什么是一致性哈希算法一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简 单哈希算法带来的问题,使得分布式哈希(DHT)可以在P2P环境中真正得到应用。一致性hash算法提出了在动态变化的Cache环境中,判定哈希算法好坏的四个定义:平衡性(Balance)单调性(Monotonicity)分散性(Spread)负载(Load)实现机制一致哈希是

2021-11-20 17:30:39 931

原创 生产者-消费者模型

什么是生产者消费者模型生产者 - 消费者模型( Producer-consumer problem) 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见。这个模型由两类线程和一个缓冲区组成来组成生产者线程:生产数据,并把数据放在这个队列里面缓冲区:存放生产者的数据的地方消费者线程:从队列里面取数据,消费数据运行流程生产者和消费者在同一时间段内共用同一个存储空间生产者往存储空间中添加产品消费者从存储空间中取走产品当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。

2021-11-20 16:43:07 6589

原创 BIO、NIO、AIO的区别

同步与异步同步和异步指的是一个执行流程中每个方法是否必须依赖前一个方法完成后才可以继续执行。假设我们现在有两个方法:方法一和方法二。同步指的是调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。即方法二一定要等到方法一执行完成后才可以执行。异步指的是调用立刻返回,调用者不必等待方法内的代码执行结束,就可以继续后续的行为。即执行方法一的时候,直接交给其他线程执行,不由主线程执行,也就不会阻塞主线程,所以方法二不必等到方法一完成即可开始执行。同步与异步关注的是方法的执行方是主线程还是其他

2021-11-18 21:21:37 348

原创 Spring AOP是怎么实现的

概述Spring的AOP实现是通过动态代理实现的。如果我们为Spring的一个bean配置了AOP切面,那么Spring在创建这个bean的时候,实际上创建的是这个bean的一个代理对象,我们后续对bean中方法的调用,实际上调用的是代理类重写的代理方法。而Spring的AOP使用了两种动态代理,分别是JDK的动态代理;CGLib的动态代理。JDK动态代理Spring默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理。JDK实现动态代理需要两个组件

2021-11-17 23:33:36 5139 1

原创 Java的反射机制

什么是反射在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。两种表现类型Java程序中的对象在运行时可以表现为两种类型,即编译时类型运行时类型例如 User user = new Admin(); 这行代码将会生成一个user变量,该变量的编译时类型为User,运行时类型为Admin。

2021-11-17 23:06:19 670

原创 MySQL如何避免幻读

事务的并发问题脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。幻读:A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。select某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。MySQL如何实现避免幻读在快照读读情况下

2021-11-14 15:24:18 2246

原创 RabbitMQ的死信队列

什么是死信在 RabbitMQ 中充当主角的就是消息,在不同场景下,消息会有不同地表现。死信就是消息在特定场景下的一种表现形式,这些场景包括:消息被拒绝访问,即 RabbitMQ返回 nack 的信号时消息的 TTL 过期时消息队列达到最大长度消息不能入队时。上述场景经常产生死信,即消息在这些场景中时,被称为死信。什么是死信队列死信队列就是用于储存死信的消息队列,在死信队列中,有且只有死信构成,不会存在其余类型的消息。死信队列在 RabbitMQ 中并不会单独存在,往往死信队列都会绑

2021-11-13 14:51:16 6756 1

原创 红黑树是什么

红黑树红黑树是一种接近平衡的二叉搜索树,它能够保证任意一个节点左右子树的高度差不会超过较低子树的高度,也就是两棵子树的高度比值不会超过 2 倍。这样我们可以使搜索的时间复杂度更接近 O (logN)。为了保证树的平衡,我们需要在添加或删除元素的时候不断的调整树的结构,使每个节点的左右子树上的节点个数尽可能相等。红黑树的性质每个节点不是红色就是黑色;根节点永远是黑色;红色节点的子节点必须是黑色;任意一个节点到每个叶子节点的路径上都包含相同数量的黑色节点;每次添加新节点都默认为红色。红黑树调

2021-11-13 14:03:33 728

原创 select、poll和epoll的区别

进程所能打开的最大连接数select单个进程所能打开的最大连接数有FD_ SETSIZE宏定义, 其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_ SETSIZE为3264)tips:我们可以对进行修改,然后重新编译内核,但是性能可能会受到影响,这需要进一步的测试。pollpoll本质上和select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的epoll虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接,2G内存的机器可

2021-11-06 19:54:41 3338 1

原创 IO多路复用

概述IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu;多路是指网络连接,复用指的是同一个线程。三种实现方式select时间复杂度O(n),它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差

2021-11-06 15:50:24 162

原创 分布式事务之三阶段提交

三阶段提交协议是两阶段提交协议的改进版本,它通过超时机制解决了阻塞的问题,并且把两个阶段增加为三个阶段。流程询问阶段协调者询问参与者是否可以完成指令,协调者只需要回答是或不是,而不需要做真正的操作,这个阶段超时会导致中止。准备阶段如果在询问阶段所有参与者都返回可以执行操作,则协调者向参与者发送预执行请求,然后参与者写redo和undo日志,执行操作但是不提交操作;如果在询问阶段任意参与者返回不能执行操作的结果,则协调者向参与者发送中止请求,这里的逻辑与两阶段提交协议的准备阶段是相似的。

2021-10-31 17:43:25 272

原创 分布式事务之两阶段提交

两阶段提交协议两阶段提交协议把分布式事务分为两个阶段,一个是准备阶段,另一个是提交阶段;准备阶段和提交阶段都是由事务管理器发起的;我们可以将事务管理器称为协调者,将资源管理器称为参与者。流程准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,则会写redo或者undo日志(Write-Ahead Log的一种),然后锁定资源,执行操作,但是并不提交。提交阶段:如果每个参与者明确返回准备成功,也就是预留资源和执行操作成功,则协调者向参与者发起提交指令,参

2021-10-31 17:21:05 3503

原创 RabbitMQ 如何保证消息不会被重复消费

所有的消息队列都要保证同一条消息不会被重复消费举个例子:假设有个系统,消费一条往数据库里插入一条,要是你一个消息重复两次,你不就插入了两条,这数据就错了所以消费到第二次的时候,自己判断一下已经消费过了,直接扔了,就保留了一条数据一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性幂等性。一个请求重复多次,需要确保对应的数据是不会改变的,不能出错。为什么会重复消费(1)生产者重复发送消息:生产者在往消息队列发送消息时,发生了网络抖动,生产者没有收到确认信号,但是实际上消息队

2021-10-30 21:17:39 4790

原创 RabbitMQ如何保证顺序消费

为什么要顺序消费保证消息的顺序消费是生产业务场景下经常面临的挑战,例如电商的下单逻辑,在用户下单之后,会发送创建订单和扣减库存的消息,我们需要保证扣减库存在创建订单之后执行。处理业务逻辑后,向MQ发送一条消息,再由消费者从 MQ 中获取 消息落盘到MySQL 中。在这个过程中,可能会有增删改的操作,比如执行顺序是增加、修改、删除。消费者可能换了顺序给执行成删除、修改、增加,所以我们要保证消息的顺序消费为什么会不按顺序消费对于 RabbitMQ 来说,导致上面顺序错乱的原因通常是消费者是集群部

2021-10-30 20:57:28 10780 10

原创 TCP的粘包和拆包

什么是粘包和拆包一个完整的业务数据包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和粘包问题。第一种情况(正常)接收端正常收到两个数据包,即没有发生拆包和粘包的现象;第二种情况接收端只收到一个数据包,由于TCP是不会出现丢包的,所以这一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。这种情况由于接收端不知道这两个数据包的界限,所以对于接收端来说很难处理。第三种情况接收端收到了两个数据包,但是这两个数据包要么是不完整的

2021-10-13 22:25:47 885

Tcpdump学习笔记.docx

tcpdump是一个用于截取网络分组,并输出分组内容的工具。凭借强大的功能和灵活的截取策略,使其成为类UNIX系统下用于网络分析和问题排查的首选工具 tcpdump 支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。

2020-07-03

空空如也

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

TA关注的人

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