自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(127)
  • 资源 (1)
  • 收藏
  • 关注

原创 go实现的简单压测工具

可以看到prometheus在http server端统计到的数据qps、tp99、tp90、tp95基本上是符合的,由此验证工具正确性。为验证工具统计正确性,配置prometheus进行对照。启动后打开localhost:9090查看。官网下载zip安装包,解压启动即可。TP99、TP95修改对应值即可。grafana面板配置。进行http接口请求。

2023-06-26 15:54:10 595

原创 chat聊天系统消息消费时遇到的问题及优化思路(二)

考虑下面几个条件下如何提升kafka的消费速度消息要求严格有序,如chat聊天消息业务处理速度慢,如处理一条数据需要100ms分片不合理,如有的分区很闲,有的分区消息数量积压。

2023-06-05 15:27:10 618

原创 git repack多包使用及相关性能测试

git server端 objects 打包时单包与多包对比测试

2023-03-02 11:09:54 773

原创 chat聊天系统消息消费时遇到的问题及优化思路(一)

从consumer端优化处理kafka lag及消费慢的几种常见问题

2023-01-31 11:48:37 595

原创 redis string类型

1、string类型使用场景计数,如点赞数、限制请求次数、pv/uv等作为key-value缓存基础数据存储session,以实现分布式下的共享session2、数据结构redis为c语言编写的,但是c语言没有String类型,只有cha[]类型,而且char数组在初始化的时候指定完大小后就不能再改变了。基于此,redis维护了一个自己的数据结构——SDS(Simple Dynamic String)。SDS兼容C语言标准字符串处理函数,且在此基础上保证了二进制安全。2.1、二进制安全在

2022-02-11 15:41:28 1214

原创 golang基础知识整理

1、声明map//第一种方式var m1 map[string]stringm1 = make(map[string]string)m1["a"] = "aa"m1["b"] = "bb"//第二种方式m2 := make(map[string][string])m2["c"] = "cc"//第三种方式m3 := map[string]string{ "a": "aa", "b": "bb",}//查找键值是否存在if v, ok := map["a"];ok{

2021-10-11 11:56:15 202

原创 TCP、UDP与IP首部

1、TCP首部1、TCP虽然是面向字节的,但传输的时候数据单元却是报文段,一个TCP报文段分为首部和数据两部分,TCP的首部前20个字节是固定的,后面的4n个字节根据需要来增加,因此TCP报文最小的长度为20字节。引用一张图各字段含义如下:1、源端口和目的端口:顾名思义,各占两个字节;2、序号,占4个字节,范围是0-2^ 31 -1,序号采用的是 mod 2 ^ 32,当到达最大之后会再次从0开始,这个序号是用来标识报文段对应的字节的开始和结束范围,例如,一报文段的序号是301,而接待的数据共

2020-09-11 17:55:11 1429

原创 HTTP报文

1、请求报文引用两张图一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。请求行有请求方法、请求URL、请求HTTP协议的版本请求方法有这么几种:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT1.1、请求方法:①、GET传递参数长度受限制,因为传递的参数是直接表示在地址栏中,而特定浏览器和服务器对url的长度是有限制的。因此,GET不适合用来传递私密数据,也不适合拿来传递大量数据。一般

2020-08-14 15:31:13 260

原创 TCP三次握手与四次挥手

1、TCP三次握手建立连接引用一张图三次握手过程:①、客户端向服务端发送请求,将首部中的同步字段(SYN)置为1,只有SYN = 1才能表明客户端想建立连接,并随机选择一个初始序列号x,但此时SYN中并没有携带数据,但是仍然要消耗一个序列号,也就是说下次发送的时候序列号seq = x + 1,此时进入同步已发送状态。②、服务器收到客户端的请求,将SYN和ACK都置为1,SYN为1表示服务端想要与客户端建立连接,ACK表示服务端同意与客户端建立连接,确认号为x+1,表示服务端下次想要接收的报文的第

2020-08-11 11:46:53 208

原创 查漏补缺

1、CMS与stop-the-worldSTOP THE WORLDstop the world意味着从应用中停下来并进入到GC过程中去,一旦stop-the-world发生,除了GC所需要的线程外,其他线程都将停止工作,中断了的线程直到GC任务结束才继续它们的任务。CMS收集器是一种以获取最短回收停顿时间为目标的收集器,CMS收集器是基于“”标记–清除”(Mark-Sweep)算法实现的,整个过程分为四个步骤:①、初始标记,会引起stop-the-world,只标注对象是否到GC-Roots存在

2020-08-10 17:44:23 182

原创 MySQL相关问题记录

1、MySQL三范式①、第一范式:每个列都不可以再分,也就是说每一列存储的内容都不可以再拆分,如地址就应该按照省、市、区等分别创建字段,而不应该放在一个字段中。②、第二范式:在第一范式的基础上,非主键要完全依赖于主键,而不能部份依赖,换句话说就是一张表只能说明一个事物。③、第三范式,在第二范式的基础上,非主键只能依赖于主键,简而言之,第三范式要求一个数据库表中不包含已在其它表中已包含的非主键字段。就是说,表的信息,如果能够被推导出来,就不应该单独的设计一个字段来存放(能尽量外键join就用外键join

2020-08-06 14:57:36 113

原创 HashMap、HashTable与ConcurrentHashMap

概述为了解决HashMap 的线程不安全,有三种解决方法使用Collections.synchronizedMap(map)使用HashTable使用ConcurrentHashMap考虑到并发度等问题用的最多的是最后一种,它的性能和效率明显高于前面两种。1、Collections.synchronizedMap再synchronizedMap内部维护了一个普通话对象map和排斥锁mutexprivate final Map<K,V> m; // Backing Ma

2020-08-04 14:30:49 187

转载 Redis缓存与MySQL数据一致性问题

概述引用一张图理论上来说为key设置过期时间是保证数据一致性的方案,为缓存设置了过期时间,所有的写操作以数据库为准,对缓存做到尽力即可,因为即使缓存时脏数据,过期时间到了之后自然会被淘汰。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。这里讨论的三种策略是不对key设置过期时间的:先更新数据库,再更新缓存;先删除缓存,再更新数据库;现更新数据库,再删除缓存1、先更新数据库,再更新缓存这种方案一般不被使用,考虑下面情况假

2020-08-03 19:31:37 163

原创 Redis的分布式寻址算法

概述Redis的分布式寻址算法有三种:hash算法一致性hash算法redis-cluster的hash slot算法1、hash算法首先计算哈希值,然后对节点数量取模,此时如果节点增加或者减少必然会导致获取到的缓存数据出错,如果节点宕机甚至还会导致缓存雪崩,导致数据库瘫痪。2、一致性哈希一致性哈希把哈希空间形成一个虚拟的环,将key的哈希值取模运算后顺时针走动,遇到的第一个节点就是其存储的位置。如果一个节点挂掉了影响的只是此节点和逆时针走动到上一个节点之间的数据,其他不受影响,增加一个

2020-08-03 17:00:09 968

原创 Redis相关问题

1、redis-cluster集群使用主从复制当master挂掉之后系统不能自动选举出新的master,系统也就不能对外提供写功能;使用哨兵模式虽然解决了自动选举的问题,但是不能动态扩展,下面介绍redis-cluster。redis-cluster集群中有多个master节点,每个master都可读可写,节点之间相互通信,redis-cluster集群无中心节点,无需哨兵监控。常见问题:①、Redis是如何进行持久化的?Redis是基于内存的,因此持久化是必不可少的,在Redis中持久化有两种方

2020-08-03 15:20:39 123

转载 Redis五种数据结构底层实现简析

1、字符串Redis的字符串是基于C语言的,没有Java这种操作字符串的类库,因此Redis自动封装了一个,为SDS(Simple Dynamic String),SDS中包含了三个属性:len,buf中已经占有的字符串长度(字符串实际长度)free,buf中未使用的缓冲区长度buf[ ],实际保存字符串的地方因此获取字符串长度时间复杂度为O(1),buf[ ]中采用了C语言的\0结尾,因此可以使用C语言的标准字符函数。分配原则:当字符串长度小于1MB时,分配字符串时分配空间的大小为字符串长

2020-08-02 15:23:15 5004

原创 常见设计模式

1、单例①、懒汉式public class SingleModel { private static SingleModel instance; private SingleModel() { } public static SingleModel getInstance(){ if (instance == null){ instance = new SingleModel(); } retur

2020-07-28 19:34:16 111

原创 基于Redis和RabbitMQ简单实现秒杀回顾

概述使用springboot + druid + redis + rabbitmq实现简单的秒杀系统,大致思路如下:①、启动服务,缓存预热,将需要被秒杀的商品加载进redis缓存中,使用redis简单的string数据类型,key为商品ID,value为商品数量;②、登录之后,选择可以秒杀的商品,可选操作有加入购物车和立即抢购;③、点击抢购之后首先根据所选的商品ID查询redis,看是否商品数量小于等于0,如果是,则直接返回商品已售罄,否则将请求加入rabbitmq队列;④、入队之后进行发送端发

2020-07-28 17:02:39 3502 1

原创 ConcurrentHashMap

概述HashMap是线程不安全的,当多个线程同时put的时候可能会导致死锁,针对这一点,有HashTable可以解决,但HashTable效率很低,使用synchronized加锁,导致多个线程竞争同一把锁,于是出现了ConcurrentHashMap。1、ConcurrentHashMap-1.7相比于将整个HashMap锁住,采用分段锁将HashMap分为几段分别加锁,这样就减少了锁的竞争。ConcurrentHashMap使用分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一

2020-07-27 13:43:22 87

原创 线程池与阻塞队列

1、概述由于频繁的创建和销毁线程会消耗很多资源,因此线程池应运而生来去除频繁的创建与删除线程这一过程。2、常见线程池①、newSingleThreadExecutor单一线程池,使用唯一的工作线程执行任务,保证所有任务按照指定顺序执行。ExecutorService service = Executors.newSingleThreadExecutor();底层实现是FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例publi

2020-07-27 11:23:29 1049 1

原创 ThreadLocal常用操作及原理

概述ThreadLocal并不是为了解决线程间共享变量的问题,而是提供线程内部共享变量,在多线程环境下可以保证各个线程之间的变量相互独立互不影响。可以通过set()/get()方法设置和获取元素值。1、get()方法public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e

2020-07-24 14:53:07 223

原创 Java多线程相关

1、Java中的线程调度算法一种是分时调度,让所有的线程轮流获得CPU的使用权,并且平均分配每个线程占用的CPU时间片。另一种是抢占式任务调度,可以让优先级高的优先执行,如果优先级相等就随机选一个执行。线程调度器: 是一个操作系统服务,负责为一个可运行状态的线程分配CPU时间片。一旦创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片 是指可用的CPU时间片分配给可用的就绪线程的过程2、sleep()函数与wait()函数的区别sleep()不会释放锁,是Thread类的方法;

2020-07-24 13:42:31 144

原创 Spring解决循环依赖问题

概述这里的循环依赖说的是对象之间的循环依赖,如上图,A依赖于B,B依赖于C,C依赖于A,形成一个死循环。在Spring中循环依赖场景有两种:构造器的循环依赖;setter的循环依赖其中构造器的循环依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常;对于setter的循环依赖,spring采用提前暴露对象的方法解决。1、spring如何检查循环依赖Bean在创建的时候给这个Bean打上标志,如果递归调用回来发现正在创建中的话就说明循环依赖。3、

2020-07-23 19:54:03 271

原创 基于ReeentrantLock的AQS实现

概述AQS,AbstractQueuedSynchronizer,是一个抽象类,定义了同步状态的获取和释放方法来供自定义的同步组件使用,AQS的实现依赖于内部的同步队列(FIFO),当线程获取同步状态失败后就会被封装成一个Node节点加入同步队列的尾部,并阻塞该线程,当同步状态释放时唤醒队列头节点。AQS中最重要的三个成员变量private transient volatile Node head;private transient volatile Node tail;private volat

2020-07-23 15:04:18 114

原创 线程与进程

1、线程与进程的区别与联系①、进程,进程是操作系统资源分配和调度的最小单位,在系统中一般是一个程序的执行。②、线程,线程是处理器任务调度和执行的基本单位,一个进程有多个线程。为什么切换线程比切换进程开销小对于一个程序来说,进程启动后会使用很多资源,比如寄存器、内存、文件等,这些在进程切换的时候必须要考虑保存当前进程的状态,包括存放在内存中的程序的代码和数据、栈、通用寄存器的内容、程序计数器、环境变量以及打开的文件描述符的集合,这个状态叫做上下文。在一个进程中包含了很多线程,每个线程也都有自己的上下

2020-07-22 16:29:03 79

原创 Java NIO基本概念

综述NIO是Java1.4之后的新的一套IO接口,可以理解为非阻塞而不仅仅是new。1、IO与NIO的区别IO是面向流的,如字节流和字符流;而NIO是面向缓冲的。IO是阻塞的,NIO是非阻塞的。NIO有选择器,而IO没有。2、NIO基本概念①、SelectorNIO引入了Selector选择器来监听多个通道事件,可以将多个通道注册到同一个Selector选择器中,然后创建一个线程管理这个选择器,这种情况下一个线程可以管理多个通道,并能够知道读写事件是否做好准备。②、Channel和B

2020-07-17 17:49:44 226

原创 IO多路复用select,poll,epoll

多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select/poll传入多个文件描述符(FileDescription 简称FD),如果有一个文件描述符准备就绪就返回,否则一直阻塞到超时。IO多路复用是一种机制,一个进程监控多个文件描述符,一旦某个文件描述符准备就绪就通知进程执行相应的IO操作,但select、poll、epoll本质上是同步IO,需要在读写事件就绪后自己负责读写,也就是说这个读写过程是阻塞的。而异步IO无需自己处理读写,而是把读写交给了内核。与多线程

2020-07-15 17:41:58 156

原创 Java IO流

综述流代表任何有能力产出数据的数据源对象,或者是有能力接受数据的接收端对象。流的本质是数据传输,根据数据传输类型,将流分为各种类,分别操作。1、装饰者模式装饰,类似于装饰房间,每添加一件装饰物品,房间气氛都会改变,装饰者模式也起到这样的作用,动态的为一个对象添加其他功能,装饰者提供了一种灵活的方式来替换继承。装饰者模式的框架如下:Component,也就是我们需要装饰的对象,他是抽象的,定义了一些方法,实际上要装饰的就是它的方法。ConcreteComponent,上述对象子类化后的对象,

2020-07-15 16:11:55 98

原创 Java泛型

综述泛型,也即参数化类型,所谓的参数化类型,也就是将原来的具体的类型参数化,类似于方法中的类型参数,此时参数的类型也定义成了参数形式,然后在调用时传入具体的类型。泛型的本质就是参数化类型,也就是在泛型使用的过程中操作的数据类型被指定为一个参数,这种类型可以用在类、接口和方法中,分别构成泛型类、泛型接口和泛型方法。1、泛型的特性泛型只在编译阶段有效,在编译之后程序会采用去泛型化的操作,下面的例子就可以证明:List<String> stringList = new ArrayList&l

2020-07-15 10:20:12 69

原创 Java stream流

综述stream流提供可以以一种声明的方式处理数据,是一个来自数据源的元素队列并支持聚合操作。原元素是特定类型的对象,形成一个队列。stream并不会存储元素,而是按需计算。数据源 也即是流的来源,可以是集合、数组、IO/channel等。聚合操作,如filter, map, reduce, find, match, sorted等。要得到一个stream通常不会手动创建,而是调用已存在的方法如:Collection.stream()Collection.parallelStream()

2020-07-15 09:36:46 267

原创 Collections与Arrays常用函数

一、Collections估工具类1、Collections.sort()排序函数此方法是对List类型的数据进行排序,对于自定义的实体类存入的list想要调用此函数排序,则实体类要实现Comparable接口并重写compareTo()方法,也可以实体类不实现Comparable接口,但是需要自定义一个类实现Comaprator接口并重写compare()方法。Collections.sort()的两种形式public static <T extends Comparable<? su

2020-07-14 15:17:47 207

原创 Java集合类之HashMap

综述HashMap是一个存储键值对(Key-value)的集合,每一组键值对也叫做Entry,HashMap数组的初始化都是null。1、成员变量//初始化容量为16,这个必须是2的幂static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//负载因子static final float DEFAULT_LOAD_FACTOR = 0.75f;//大于这个阈值会将链表转化为红黑树static final int TREEIFY_THR

2020-07-14 13:50:40 299

原创 理解红黑树插入与删除

综述红黑树是一个自平衡的二叉查找树,在插入和删除等可能破坏树的平衡时需要自动调整平衡,红黑树的定义就是红黑树是一种含有红黑结点并能自平衡的二叉查找树。红黑树的性质①、每个节点要么是红色的要么是黑色的;②、根节点是黑色的;③、每个叶子节点(NIL)都是黑色的;④、每个红色节点的两个子节点一定都是黑色的;⑤、任意一节点到每个叶子节点的路径都包含相同数量的黑色节点从性质⑤可推出结论:如果一个节点存在黑色的子节点,那么这个节点肯定有两个子节点。关于左旋和右旋问题,以下面两张图为例进行理解:

2020-07-13 19:37:47 372

原创 Java集合类之ArrayList

概述图片来自菜鸟教程由图可知,Java集合框架主要由两部分组成,一个是集合Collectin,另一个是图Map,Collection接口有三个子接口,这三个子接口下面是一些实现的抽象类,再往下就是一些实现,之所以定义这么多的接口就是为了适应不同类型的操作。1、Collection接口查看Collection接口源码,其中定义了常用的add(),get(),remove(),retainAll()(取交集)等方法。Collection接口定义了sort()排序函数,其实现是调用Arrays.so

2020-07-13 14:50:03 240

原创 HTTP与HTTPS

1、HTTPHTTP是一个超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,基于TCP/IP协议传输数据。特点:无状态:协议对客户端没有状态存储,不具有记忆能力,如访问一个网站需要进行重复登录;无连接:HTTP/1.1之前,由于无状态的原因,客户端每次建立连接都需要使用TCP进行三次握手,如果一个客户端在短时间内多次请求服务端,服务端每次都需要重新响应,造成不必要的时间浪费;基于请求和响应:有客户端发起请求,服务端响应;简单快速;通信使用明文,请求和响应不会对通信方进行确认,无法

2020-07-09 18:14:59 325

原创 SSM回顾注意事项一

1、配置文件扫描包相关<context:component-scan base-package="com.xxx,com.yyy"/>可以用逗号隔开扫描多个包;如果像扫描本包下所有的service子包(这些service子包有不同的父包),可以如下配置:<context:component-scan base-package="com.a.**.service"/>context:component-scan默认开启了<context:annotation

2020-05-22 10:35:41 191

原创 八大排序算法

常见的八大排序算法他们之间的关系如下:1、直接插入排序算法过程描述:当只有一个元素的时候是有序的,对于从第二个元素开始,逐个与前面构建的有序数列的每个元素进行比较,并且是与有序数列从后向前比较,当有序数列的指定位置值大于当前元素时,就将指定元素后移,直到找到目标位置,如下图:代码实现:public static void directInsertionSort(int[] array)...

2020-04-11 15:58:47 134

原创 SpringMVC工作原理及常见问题

1、SpringMVC工作原理图1、用户发起请求;2、DispactcherServlet接收到请求,并调用HandlerMapping查找处理器;3、HandlerMapping根据请求的URL找到处理器(可通过xml,注解进行查找),并返回给前端处理器DispatcherServlet;4、DispatcherServlet调用HandlerAdapter执行Handler;5、...

2020-04-08 12:04:20 121

原创 基于Redisson的分布式锁

1、前言基于Redis实现单节点的分布式锁详见:基于Redis实现单节点分布式锁本文使用Redisson实现Redis的主从模式、sentinel模式和Cluster模式的分布式锁2、实现过程①、引入redisson的pom依赖;②、配置SpringBootapplication.yml中的redis信息,注意不同集群模式下要切换端口;③、配置RedissonUtils,如下:pub...

2020-04-02 20:58:04 205

原创 Redis集群

1、主从模式①、主从模式的优点:为数据提供多个副本,实现高可用;实现读写分离,主节点负责写,从节点负责读,主节点定期把数据同步到从节点实现数据的一致性;避免了当单个节点损坏时数据丢失②、 主从模式的特点数据流是单向的,只能是从master流向slave;一个maste可以有多个slave,master可读可写,slave只能读,不要修改配置让slave可写,因为slave写之后...

2020-04-01 22:29:11 90

Java实现离散真值表

此文件实现了离散中的输出真值表,应用了栈的技术,可以帮助java学习者更好的巩固基础

2018-10-17

空空如也

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

TA关注的人

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