自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(34)
  • 收藏
  • 关注

原创 Netty——深入理解主从 Reactor 多线程模式

BossGroup 中的线程专门负责和客户端建立连接,WorkerGroup 中的线程专门负责处理连接上的读写。1)有两组线程池:BossGroup 和 WorkerGroup,BossGroup 中的线程(可以有多个,图中只画了一个)专门负责和客户端建立连接,WorkerGroup 中的线程专门负责处理连接上的读写。这种模式的优点是可以充分的利用多核 cpu 的处理能力,缺点是多线程数据共享和控制比较复杂,Reactor 处理所有的事件的监听和响应,在单线程中运行,面对高并发场景还是容易出现性能瓶颈。

2023-04-19 18:51:06 748

原创 Netty——如何实现长连接

一个简单的长连接demo分为以下几个步骤:长连接流程​ 看似简单的步骤,里面有两个技术难点:如何保存已创建的Channel这里我们是将Channel放在一个Map中,以Channel.hashCode()作为key其实这样做有一个劣势,就是不适合水平扩展,每个机器都有一个连接数的上线,如果需要实现多用户实时在线,对机器的数量要求会很高,在这里我们不多做讨论,不同的业务场景,设计方案也是不同的,可以在长连接方案和客户端轮询方案中进行选择。如何自动关闭没有心跳的连接。

2023-04-19 18:47:25 1246

原创 Netty——深入解析心跳检测机制

客户端定时每X秒(推荐小于60秒)向服务端发送特定数据(任意数据都可),服务端设定为X秒没有收到客户端心跳则认为客户端掉线,并关闭连接触发onClose回调。当需要服务端定时给客户端发送心跳数据时, $gateway->pingData设置为服务端要发送的心跳请求数据,心跳数据是任意的,只要客户端能识别即可。当设置为服务端主动发送心跳时,如果客户端最近有发来数据,那么证明客户端存活,服务端会省略一个心跳,下个心跳大约1.5*$gateway->pingInterval秒后发送。心跳检测时间间隔 单位:秒。

2023-04-19 18:45:51 439

原创 Netty——NIO

21:16:39 [DEBUG] [main] c.i.n.ChannelDemo6 - 连接已建立: java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:60367],可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前的 stream 要么是输入,要么是输出,channel 比 stream 更为底层。

2023-04-19 18:43:46 439

原创 JUC——AQS原理与ReentrantLock原理详解

接下来 Thread-0 竞争成功,permits 再次设置为 0,设置自己为 head 节点,断开原来的 head 节点,unpark 接下来的 Thread-3 节点,但由于 permits 是 0,因此 Thread-3 在尝试不成功后再次进入 park 状态。// 如果 head.waitStatus == 0 ==> Node.PROPAGATE。[100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%]欢迎来到英雄联盟!

2023-04-19 18:36:18 98

原创 JUC——深入解析共享模型之工具

线程池自定义线程池步骤1:自定义拒绝策略接口@FunctionalInterface // 拒绝策略步骤2:自定义任务队列// 1. 任务队列// 2. 锁// 3. 生产者条件变量// 4. 消费者条件变量// 5. 容量// 带超时阻塞获取try {// 将 timeout 统一转换为 纳秒try {// 返回值是剩余时间return t;// 阻塞获取try {try {return t;// 阻塞添加。

2023-04-11 23:43:01 122

原创 JUC——深入解析共享模型之内存

抛开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见。线程解锁 m 之前对变量的写,对于接下来对 m 加锁的其它线程对该变量的读可见x = 10;线程对 volatile 变量的写,对接下来其它线程对该变量的读可见x = 10;线程 start 前对变量的写,对该线程开始后对该变量的读可见x = 10;

2023-04-11 23:41:10 59

原创 JUC——深入解析共享模型之管程

相对于 synchronized 它具备如下特点可中断可以设置超时时间可以设置为公平锁(解决线程饥饿问题)支持多个条件变量与 synchronized 一样,都支持可重入语法:// 获取锁try {// 临界区// 释放锁。

2023-04-11 23:37:23 105

原创 Redis缓存一致性问题

延时双删的方案的思路是,为了避免更新数据库的时候,其他线程从缓存中读取不到数据,就在更新完数据库之后,再sleep一段时间,然后再次删除缓存。线程2来读缓存,发现缓存已经被删除,所以直接从数据库中读取,这时候由于线程1还没有更新完成,所以读到的是旧值,然后把旧值写入缓存。先更新数据库,成功后往消息队列发消息,消费到消息后再删除缓存,借助消息队列的重试机制来实现,达到最终一致性的效果。线程1,根据估算的时间,sleep,由于sleep的时间大于线程2读数据+写缓存的时间,所以缓存被再次删除。

2023-04-11 23:34:36 66

原创 JUC——基本概念

如果是串行执行,那么总共花费的时间是 10 + 11 + 9 + 1 = 31ms,但如果是四核 cpu,各个核心分别使用线程 1 执行计算 1,线程 2 执行计算 2,线程 3 执行计算 3,那么 3 个线程是并行的,花费时间只取决于最长的那个线程运行的时间,即 11ms 最后加上汇总时间只会花费 12ms。线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用。

2023-04-11 23:34:15 75

原创 Redis——内存淘汰机制

每当 Redis的服务器周期性操作redis.c/serverCron函数执行时, activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分 CPU时间,在内存不紧张但是CPU时间非常紧张的情况下,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。如果没有过期, 就返回该键。

2023-04-11 23:32:45 515

原创 Redis——Redis主从复制详解

主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。

2023-04-06 23:32:56 70

原创 Redis——Redis集群详解

Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。Redis 集群通过分区(partition)来提供一定程度的可用性即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。edis ACL是Access Control List(访问控制列表)的缩写,该功能允许根据可以执行的命令和可以访问的键来限制某些连接。在Redis 5版本之前,Redis 安全规则只有密码控制还有通过rename。

2023-04-06 23:31:24 970

原创 Redis——深入解析Redis事务和锁机制

Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。Redis事务的主要作用就是串联多个命令防止别的命令插队。

2023-04-06 23:31:06 101

原创 Redis——持久化详解

在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。dump.rdb文件在

2023-04-06 23:29:21 59

原创 Redis——常用五大数据类型

String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M单键多值Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

2023-04-06 23:27:30 88

原创 高性能Mysql——查询性能优化详解

前面的章节我们介绍了如何设计最优的库表结构、如何建立最好的索引,这些对于高性能来说是必不可少的。但这些还不够一还需要合理的设计查询。如果查询写得很糟糕,即使库表结构再合理、索引再合适,也无法实现高性能。查询优化、索引优化、库表结构优化需要齐头并进,一个不落。在获得编写MySQL查询的经验的同时,也将学习到如何为高效的查询设计表和索引。同样的,也可以学习到在优化库表结构时会影响到哪些类型的查询。这个过程需要时间,所以建议大家在学习后面章节的时候多回头看看这三章的内容。本章将从查询设计的一-些基

2023-04-06 00:11:09 382

原创 高性能Mysql——创建高性能索引详解

索引(在MySQL中也叫做“键(key)”)是存储引擎用于快速找到记录的一种数据结构。这是索引的基本功能,除此之外,本章还将讨论索引其他一些方面有用的属性。索引对于良好的性能非常关键。尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要。在数据量较小且负载较低时,不恰当的索引对性能的影响可能还不明显,但当数据量逐渐增大时,性能则会急剧下降。不过,索引却经常被忽略,有时候甚至被误解,所以在实际案例中经常会遇到由糟糕索引导致的问题。这也是我们把索引优化放在了靠前的章节,甚至比查询优化还靠前的

2023-04-06 00:06:16 309

原创 高性能Mysql——Schema与数据类型优化

良好的逻辑设计和物理设计是高性能的基石,应该根据系统将要执行的查询语句来设计schema,这往往需要权衡各种因素。例如,反范式的设计可以加快某些类型的查询,但同时可能使另一些类型的查询变慢。比如添加计数表和汇总表是一种很好的优化查询的方式,但这些表的维护成本可能会很高。MySQL独有的特性和实现细节对性能的影响也很大。本章和聚焦在索引优化的下一章,覆盖了MySQL特有的schema设计方面的主题。我们假设读者已经知道如何设计数据库,所以本章既不会介绍如何入门数据库设计,也不会讲解数据库设计方面的深入

2023-04-06 00:03:09 229

原创 高性能Mysql——深入理解事物

所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序IO,而不像随机IO需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。

2023-04-06 00:01:49 53

原创 高性能Mysql——MySQL 的存储引擎详解

创建 MyISAM表的时候,如果指定了DELAY_KEY_WRITE选项,在每次修改执行完成时,不会立刻将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区 (in-memorykey buffer),只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入到磁盘。为了更好地控制转换的过程,可以使用mysqldump工具将数据导出到文件,然后修改文件中CREATE TABLE语句的存储引擎选项,注意同时修改表名,因为同一个数据库中不能存在相同的表名,即使它们使用的是不同的存储引擎。什么样的数据量算大?

2023-04-06 00:00:36 141

原创 Mysql——并发控制详解

写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,这是出于安全策略的考虑,只有这样,才能确保在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。大多数商业数据库系统没有提供更多的选择,一般都是在表上施加行级锁(row-level lock),并以各种复杂的方式来实现,以便在锁比较多的情况下尽可能地提供更好的性能。另外,写锁也比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列的前面(写锁可以插人到锁队列中读锁的前面,反之读锁则不能插入到写锁的前面)。

2023-04-05 23:57:28 154

原创 图解HTTP

综上所述,URI 就是由某个协议方案表示的资源的定位标识符。数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起。在boundary 字符串指定的各个实体的起始行之前插入“--”标记(例如:- -AaB03x、--THIS_STRING_SEPARATES),而在多部分对象集合对应的字符串的最后插入“--”标记(例如:--AaB03x--、--THIS_STRING_SEPARATES--)作为结束。

2023-04-05 23:56:54 94

原创 计算机网络——深入理解TCP拥塞控制机制

2、由于发送方现在认为网络很很可能没有发生特别严重的阻塞(如果发生了严重阻塞的话,就不会一连有好几个报文段到达接收方,就不会导致接收方连续发送重复确认),因此与慢开始不同之处是现在不执行慢开始算法(即拥塞窗口的值不设为1个MSSS),而是把拥塞窗口的值设为慢开始门限减半后的值,而后开始执行拥塞避免算法,线性地增大拥塞窗口。为了防止拥塞窗口增长过大引起网络拥塞,还需要维护一个慢开始门限的状态变量,当拥塞窗口的值小于慢开始门限时,使用慢开始算法,一旦拥塞窗口的值大于慢开始门限的值,就改用拥塞避免算法。

2023-04-05 23:48:18 89

原创 计算机网络——TCP/IP

互联网协议入门互联网的核心是一系列协议,总称为"互联网协议"(Internet Protocol Suite)。它们对电脑如何连接和组网,做出了详尽的规定。理解了这些协议,就理解了互联网的原理。一、概述1.1 五层模型互联网的实现,分成好几层。每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持。用户接触到的,只是最上面的一层,根本没有感觉到下面的层。要理解互联网,必须从最下层开始,自下而上理解每一层的功能。如何分层有不同的模型,有的模型分七层,有的分四层。我觉得,把互联网分成

2023-04-05 23:46:24 305

原创 线程安全与锁优化

概述在软件业发展的初期,程序编写都是以算法为核心的,程序员会把数据和过程分别作为独立的部分来考虑,数据代表问题空间中的客体,程序代码则用于处理这些数据,这种思维方式直接站在计算机的角度去抽象问题和解决问题,被称为面向过程的编程思想。与此相对,面向对象的编程思想则站在现实世界的角度去抽象和解决问题,它把数据和行为都看作对象的一部分,这样可以让程序员能以符合现实世界的思维方式来编写和组织程序。面向对象的编程思想极大地提升了现代软件开发的效率和软件可以达到的规模,但是现实世界与计算机世界

2023-04-05 00:01:02 71

原创 线程安全与锁优化——深入剖析Java内存模型与线程

在这种混合模式中,用户线程与轻量级进程的数量比是不定的,是N:M的关系,这种就是多对多的线程模型。读者试想一下,如果定义initialized变量时没有使用volatile修饰,就可能会由于指令重排序的优化,导致位于线程A中最后一条代“initialized=true”被提前执行(这里虽然使用Java作为伪代码,但所指的重排序优化是机器级的优化操作,提前执行是指这条语句对应的汇编代码被提前执行),这样在线程B中使用配置信息的代码就可能出现错误,而volatile关键字则可以避免此类情况的发生。

2023-04-04 23:55:59 79

原创 深入理解JVM——深入解析虚拟机字节码执行引擎

而对于执行引擎来讲,在活动线程中,只有位于栈顶的方法才是在运行的,也只有位于栈顶的栈帧才是生效的,称其为“当前栈帧”,与这个栈帧所关联的方法被称作为“当前方法”。所有方法调用的目标方法在Class文件里面都是一个常量池中的符号引用,在类加载的解析阶段,会将其中的一部分符号引用转化为直接引用,这种解析能够成立的前提是:方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。另外在概念模型中,两个不同栈帧作为不同方法的虚拟机栈的元素,是完全相互独立的。

2023-04-04 21:51:55 94

原创 深入理解JVM——深入解析内存区域与内存溢出异常

并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。运行时常量池是方法区的一部分。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,Java世界里“几乎”所有的对象都在实例这里分配内存。

2023-04-04 21:47:49 51

原创 深入理解JVM——深入解析虚拟机类加载机制

概述Java虚拟机把描述类的数据从Class文件中加载到内存,并对数据进行校验、转换解析和初始化,最终形参了可以被虚拟机直接使用的Java类型,这个过程乘坐虚拟机打的类加载机制。与那些在编译时需要进行连接的语言不同,Java语言里面,类型的加载、连接和初始化过程都是在程序运行期间才会完成的,这种策略会在提前编译时遇到额外的困难,也会让类加载时稍微增加一些性能开销,但是却为Java应用提供了极高的扩展性和灵活性,Java天生可以动态扩展的语言特性就是依赖运行期动态加载和动态连接这个特点实现的。类加载

2023-04-04 12:13:08 122

原创 深入理解JVM——监控和故障处理及内存调优详解

对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。过多的GC和Full GC会占用很多的系统资源(主要是CPU),影响系统的吞吐量。4)调整GC类型和内存分配,使⽤1台和多台机器进⾏测试,进⾏性能的对⽐。3)如果参数设置合理,没有超时⽇志,GC频率GC耗时都不⾼则没有GC优化的必要,如果GC时间超过1秒或者频繁GC,则必须优化。,jhat内置了⼀个微型的HTTP/HTML服务器,⽣成dump的分析结果后,可以在浏览器中查看。,⽤于对JVM中内存,线程和类等的监控。

2023-04-04 12:08:35 113 1

原创 深入理解JVM——内存分配和垃圾回收策略详解

经典垃圾收集器Serial收集器这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。“Stop The World”这个词语也许听起来很酷,但这项工作是由虚拟机在后台自动发起和自动完成的,在用户不可知、不可控的情况下把用户的正常工作的线程全部停掉,这对很多应用来说都是不能接受的。迄今为止,它依然是HotSpot虚拟机运行在客户端模式下的默认新生

2023-04-04 12:03:05 324 1

原创 深入理解JVM——垃圾回收机制深入解析

1、概述垃圾收集需要完成的三件事情:·哪些内存需要回收?·什么时候回收?·如何回收?对象已死?在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是确定哪些对象还活着,哪些已经死去,(死去指不可能再被任何途径使用的对象)。引用计数算法在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一,当引用失效时,计数器值就减一,任何时刻计数器为零时就是不可再被使用了。引用技术算法虽然占用了一些额外的内存空间进行计数,但它的原理简单,判定

2023-04-04 11:59:50 124 1

原创 JVM问题——解决方案

JVM问题怎样算JVM问题,JVM问题的特征有哪些?在JVM内存中是否出现频繁GC,特别是fullGC比较频繁,GC动作会挂起应用线程,严重影响性能。查看线程的运行情况,线程是否阻塞、是否出现了死锁。宿主机器问题、排查日志,检查程序代码当minor GC过于频繁,或发现经常出现 minor GC时,Survivor的一个区域空间满,且 Old Gen 增长超过了Survivor区域大小时,就需要考虑新生代大小的调整了。-- a.避免新生代大小设置过小Full GC频繁执行,m

2023-04-04 11:51:15 198 2

空空如也

空空如也

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

TA关注的人

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