自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 HTTP 和 HTTPS

HTTP 采用 TCP 协议作为运输层载体,默认使用 80 端口,客户端发起一个与服务器的 TCP 连接,一旦连接建立,客户端和服务器就可以通过套接字接口访问 TCP,客户端和服务器从套接字接口发送和接受 HTTP 报文套接字:socket,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象目前 HTTP 通信内容都是以明文的方式发送,不通过任何方式对数据加密。这就可能导致数据包被拦截并窃取,用户信息泄露。为了解决该问题,以安全为目标的 HTTPS 协议提出了,它在 HTTP 协议的基础上

2021-07-07 14:38:08 82

原创 HTTP 1.X 和 HTTP 2.0 的区别

1、支持多路复用在 HTTP 1.1 协议中,客户端(浏览器)针对同一域名的请求有一定的数量限制。超过限制数目的请求会被阻塞。为了尽可能快的加载静态文件,常常使用 CDN 保存静态资源加快访问HTTP 2.0 的多路复用允许同时通过单一的 HTTP 连接发起多重请求,可以很容易的实现多流并行而不依赖多个 TCP 连接。它把协议通话的基本单位缩小为帧,每个帧对应一条逻辑信息,并行地在同一个 TCP 上交换信息2、二进制分帧HTTP 2.0 在应用层和传输层之间增加二进制分帧层。在二进制分帧层,HTTP

2021-07-06 18:06:14 249 1

原创 HTTP 1.0 和 HTTP 1.1 的区别

HTTP 1.1 相比 HTTP 1.0 主要包含以下几个方面的增强:1、支持长连接HTTP 1.0 采用无连接模式,每次请求建立新的 TCP 连接,响应结束后断开连接。从 HTTP 1.1 开始默认使用长连接,所谓长连接是指客户端以及服务器复用同一套 TCP 连接,旧版本的 HTTP 要想使用长连接可以通过以下通用头配置实现:Connection: keep-alive2、节约带宽HTTP 1.0 客户端在请求某个资源时,默认服务端将整个资源返回客户端。但很多时候客户端并不一定需要所有信息。H

2021-07-06 16:26:28 999

原创 HTTP 协议

HTTP 全称超文本传输协议,是 OSI 七层模型中应用层协议,万维网数据通信的基础,通过它定义了用户到网站请求和应答的标准。HTTP 协议采用请求/响应模型,客户端向服务端发送请求报文,请求报文包含请求的方法、URL、协议版本,请求头以及请求数据。服务端以一个状态行作为响应,响应的内容还包含协议的版本、成功或错误代码、服务端信息,响应头部和响应数据URL 全称统一资源定位符,是 Internet 上标准资源的地址,URL 指示资源的位置以及用于访问它的协议所谓请求/响应模型是指请求只能从客户端发

2021-07-06 15:42:36 163

原创 OSI 七层模型与 TCP 四层模型

OSI 七层模型全称开放式通信系统互连参考协议,是一种试图使各种计算机在世界范围内互联为网络的标准框架。它将计算机网络体系结构划分为七层,每一层实现各自的功能和协议,并完成与相邻层的接口通信:应用层:通过应用程序间的交互来完成特定的网络应用。该层协议定义了应用程序间的交互规则表示层:使通信的应用程序能够解释交换数据的含义,主要包括数据压缩、数据解密及数据描述会话层:负责建立、管理和终止表示层实体之间的通信会话。该层提供了数据交换的定界和同步功能,包括建立检查点和恢复立案的方法传输层:

2021-07-06 11:01:00 133

原创 12、组合模式

组合模式将对象组合成树状的结构,当我们访问某个对象时,对它包含的所有子对象一致访问,以此递归举个例子:张三、李四都属于三班,当我们奖励三班时,同样也会奖励张三、李四。此时张三、李四就可以看做三班的子对象,当我们处理三班时,连同张三、李四一起调用组合模式由几个模块组成:抽象构件角色:为树叶构件角色和树枝构件角色提供接口树叶构件角色:叶节点对象,不包含子对象树枝构件角色:枝节点对象,包含子对象下面通过简单示例认识组合模式:interface Component { void add(

2021-07-05 16:01:15 67

原创 11、享元模式

享元模式主要用于维护大量很类似的对象,保证每种只出现一次:在面向对象程序设计中,有时可能需要创建大量类似对象,这类对象只有部分属性不同,其它属性完全相同,如五子棋中的黑白棋,各对象之间只有颜色和坐标不同。对于这种情况就可以采用共享技术来复用重复对象,不同对象只保留一份,降低系统中对象个数,减少程序压力。享元模式通常由以下几个模块组成:抽象享元角色:所有享元对象的基石具体享元角色:实现抽象享元角色接口,它只包含共享属性非享元角色:不共享的属性,类似上面提到的颜色、坐标享元工厂:通过工厂维护享元对象

2021-07-05 15:44:15 76

原创 10、外观模式

外观模式最常用也最简单,总得来说就是将多个方法封装在一个方法中,方便一起调用。基本只要用到封装或多或少会用到外观模式举个例子:商城系统买一件商品通常包含以下操作:生成订单商品库存减一财务系统记账等等为了方便处理,我们把上述三个操作封装在一个方法中调用就叫外观模式。外观模式通常通过以下三部分组成:客户:汇总方法调用方外观角色:汇总方法子系统:需要集成在一起的子方法下面我通过一个示例介绍外观模式: */class FacadeTest { private SubS

2021-07-05 15:26:27 69

原创 Java 集合架构

Java 集合架构图如下所示:这里空心三角实线箭头表示泛化,其实就是父子类之间的继承关系、空心三角虚线箭头表示实现,就是接口与实现类之间的关系、双向箭头表示关联,是对象之间的一种引用关系、虚线箭头表示依赖,通常表现为类的方法参数用到被依赖对象如图所示,最顶层 Iterator 表示迭代器,它实现了遍历集合的方法,通常在代码中这样使用:List<Integer> list = new ArrayList<>();for (int i = 0; i < 20; i++)

2021-07-05 15:01:28 166

原创 ThreadLocal 原理

上篇博客我们提到,ThreadLocal 基于 ThreadLocalMap 实现,其中 ThreadLocalMap 是 Thread 类对象全局变量,通过它保存线程私有属性。ThreadLocalMap 类是 ThreadLocal 类的静态内部类,它的 Key 是 ThreadLocal 对象本身,value 是具体副本值。每个 ThreadLocal 对应一类副本,本篇我们来详解 ThreadLocalMap 原理:下面直接看类定义源码,这里我会省略方法,具体方法实现在后面给出:static c

2021-07-01 15:25:28 108 1

原创 ThreadLocal 详解

ThreadLocal 顾名思义“线程本地变量”,对应到 Java 代码就是线程私有变量,可以把它理解为对于同一个变量,在不同的线程包含不同的副本,并且各个副本之间相互独立下面我们通过一个示例简单认识 ThreadLocal:public class ThreadLocalTest { ThreadLocal<Long> lLocal = new ThreadLocal<>(); ThreadLocal<String> sLocal = new Th

2021-06-28 15:56:51 408

原创 9、装饰器模式

装饰器模式:在不改变类结构的情况下,增添一部分新功能。传统的装饰器模式基于继承实现,其中它主要包含以下几部分:抽象构件:规范职责具体构件:实现抽象构件抽象装饰:实现抽象构件,并包含具体构件实例,通过其子类扩展具体构件的功能具体装饰: 继承抽象装饰,实体具体增强方法代码结构如下:interface Component { void operation();}class ConcreteComponent implements Component { public Co

2021-06-28 11:30:37 77

原创 8、桥接模式

桥接模式官方给出的概念:将实体与抽象分离,使它们可以独立变化。对应到代码可以理解为将对象实体和属性分离,两者独立变化,避免使用多继承。举个例子:笔包含多种类型:铅笔、圆珠笔、钢笔等等,每种类型又对应不同的颜色,红色、蓝色、黑色。。如果使用多继承实现,最顶层定义笔抽象类,下一层继承实现铅笔、圆珠笔、钢笔,再下一层继承实现红色铅笔、蓝色铅笔等等。。。这种处理方式需要创建大量的类,并且一旦增加或者删除某个属性,都需要创建或者删除大量的类为了解决该问题,我们可以把:类型、颜色抽象出来,使两者独立变化,避免使用

2021-06-28 10:51:14 82

原创 7、适配器模式

适配器模式就是让两个原来不兼容的接口兼容,它由以下三部分组成:目标接口:需要适配的接口适配者:被适配的类适配器:通过继承或引用适配者属性的方式创建的新类继承实现方式具体实现:public class ClassAdapter { interface Target { void request(); } class Adaptee { public void specificRequest() { Sys

2021-06-24 14:08:40 82

原创 6、代理模式

代理在日常生活中很常见,比如各种代售点、代购等等,从本质来说,都是为了方便。 Java 代码中的代理不是如此,它主要是为了保护被代理对象以及增强方法功能。保护体现在客户端不能直接获取目标对象,只能获取代理类,通过代理类访问目标对象,隐藏具体实现细节。增强体现在可以增加部分其它逻辑,如打印日志操作,增强方法,实际上 Spring AOP 就是这样干的。代理模式分以下几部分组成:抽象主题类:被代理类的抽象接口或抽象类真实主题类:被代理类的具体实现代理类:提供接口,供客户端访问的代理类具体代码结构

2021-06-24 11:52:05 75

原创 5、建造者模式

建造者模式和前面提到的四种设计模式有所不同:单例模式主要确保对象唯一,单例类本身负责唯一对象的创建和维护原型模式主要方便创建同类对象,核心在于 clone() 方法工厂模式主要用于创建对象总得来说,它们都主要封装创建对象这一步,而建造者模式主要优化创建对象这一步。一般情况下,建造者模式可以和其它设计模式配合使用,下面正式开始:对于复杂对象,比如包含必填属性和非必填属性,一般有以下两种初始化方法:class A { // 必填 private int id; private String

2021-06-24 10:12:21 158 1

原创 4、抽象工厂模式

抽象工厂模式实际就是工厂方法模式的再改进,我们先简单聊聊工厂方法模式:

2021-06-24 09:26:12 90

原创 3、工厂方法模式

工厂方法模式由简单工厂模式进化而来,我们先说简单工厂模式。工厂,顾名思义生产产品,根据客户的需要,生产对应的产品。对应到 java 代码:根据不同的参数,返回不同类型的对象。并且工厂一般只生产一类产品,饮品工厂不能生产衣服一个道理。java 工厂也只能生产一类对象,即包含公共父类:public class SimpleFactory { public interface Product { } public static class ProductA implements P

2021-06-23 18:14:28 80

原创 2、原型模式

原型模式的核心在于以某个对象为模板,创建多个类似对象Java 代码通过 cloneable 接口实现原型模式,关于 cloneable 我之前单独介绍过,感兴趣的可以搜一下, 这里我只简单提一下原型模式实现:public class ProtoTypeCitation { public static void main(String[] args) throws CloneNotSupportedException { Citation citation1 = new Cita

2021-06-23 17:59:38 132

原创 1、单例模式

单例模式的核心在于某个类最多只包含一个实例,并且该实例只能由类自己来创建,对外提供接口获取唯一对象饿汉式实现:在系统启动时创建唯一实例对象,缺点在于影响项目启动速度public class HungrySingleton { private static final HungrySingleton singleton = new HungrySingleton(); private HungrySingleton() { } public static Hungry

2021-06-23 17:39:01 102

原创 设计模式概述

设计模式可以理解为面向对象设计原则下一组编码规范,是对类的封装、继承、多态以及关联关系和组合关系充分理解后精炼出的规范模型。我们学习设计模式本质也是为了能用到自己的框架代码中,目前市面上主流的框架如 Spring、Mybaits 等等或多或少都有借鉴和使用设计模式,下面正式开始:目前总结出的设计模式有23种,根据目的可以分为以下三大类:创造型:描述如何创建对象,将对象的创建与使用分离结构型:描述如何将类或对象按某种布局组成更大结构行为型:描述类或对象之间如何协作实现单个对象无法实现的操作,以及怎

2021-06-23 16:30:13 73

原创 慢查询 SQL 调优

调优第一步,开启 MySQL 慢查询日志,找出慢查询 SQL:// 开启慢查询日志set global slow_query_log = ON;// 设置慢查询超时时间(单位秒)set global long_query_time = 'xxx';// 设置慢查询日志名称,默认名称:hostname-slow.logset global log-slow-queries = 'xxx';// 设置记录没有使用索引的 SQLset global log_querise_not_using_in

2021-06-22 11:35:37 394

原创 MySQL 日志

MySQL 常见日志有以下七种:binlog 日志redo logundo log慢查询日志一般查询日志中继日志错误日志binlog 是 Server 层的日志,主要用于归档,在主备同步、备份、恢复数据时发挥作用,常见格式有 row,mixed,statement 三种。redo log 是 InnoDB 特有的日志,主要用于确保事务的持久性。InnoDB 为了提高数据库的性能,每次有 SQL 请求时没有同步到磁盘,而是先保存在内存中,...

2021-06-18 11:30:06 100 1

原创 MySQL 整体架构

从整体架构来说,MySQL 可以分为服务层和存储引擎层:服务层:管理连接、缓存、SQL 验证优化、SQL 执行等存储引擎层:负责数据处理,向上提供接口服务层包含:连接器、缓存、分析器、优化器、执行器、存储过程、触发器、视图和内置函数连接器主要负责管理客户端的连接、权限验证等。我们可以通过 show processlist 查看当前连接的状态。用户的权限只在连接建立时获取,后续管理员修改不会影响当前已连接用户的权限。连接默认保持 8 小时,超时自动断开。这样做的好处在于,短时间内客户端一直使用同

2021-06-17 15:49:05 113

原创 进程的通信方式

进程间常见的通信方式有以下几种:管道信号量消息队列信号共享内存套接字管道分为以下两种:普通管道(PIPE):单向传输,只能在有亲缘关系的进程之间命名管道(FIFO):单向传输,可以在没有亲缘关系的进程之间管道是一块受内核管理的缓冲区,一端连接进程的输入,进程调用 pipe_wrtie() 方法向管道中写入数据,另一端连接另一个进程的输出,进程调用 pipe_read() 方法从管道中读取数据。为了保证两个进程对管道的操作同步,内核使用了锁、等待队列和信号等同步机制:每次写操

2021-06-15 17:32:08 122

原创 MySQL 锁

快照读:普通的 select 语句,基于 MVCC 和 undo log 实现,不加锁当前读:update、delete、insert,select…lock in share mode (共享读锁) 等操作,基于锁实现当我们执行 update、delete 操作时,首先需要找到对应的记录再操作、insert 操作类似,需找到最后一条数据,确保两条并行的 insert 不会混合插入到同一行。此时读操作就采用当前读实现,当前读每次读取最新的数据,基于锁实现。根据机制不同,锁可以分为以下两种:共.

2021-06-15 12:14:25 184 1

原创 Session 和 Cookie 的区别

Session 是由于 HTTP 协议无状态,但服务端需要区别用户而衍生出的概念,表示“会话”的意思。其中 Session 保存在服务端,每个用户对应一个 Session。服务端保存 Session 的方式有很多:内存、数据库,文件等。在分布式场景下,还需要考虑 Session 在各服务端间的共享,此时一般通过单独的缓存服务器如 Memcached、Redis 来保存 Session。然而光有 Session 是往往不够的,服务端还需要根据浏览器请求找到对应的 Session,这时就需要 Cookie 登

2021-06-10 10:20:59 82

原创 MySQL MVCC

隔离级别定义了事务必须与其他事务进行资源或数据更新相隔离的程度,MySQL InnoDB 事务默认采用可重复读隔离级别,其中可重复读通过 MVCC 实现。MVCC :Muit-Version Cnncurrency Control,多版本并发控制,它是一种并发控制的方法,在数据库管理系统中实现对数据库的并发访问。实现:InnoDB 会在每条记录后面增加三个隐藏字段:DB_ROW_ID:行 ID,随着插入操作单调递增,如果数据包含主键,则不会创建该行DB_TRX_ID:记录插入或更新该行的事务 ID

2021-06-09 14:33:51 159 2

原创 上下文切换

上下文切换是指内核在 CPU 上对进程或者线程进行切换:进程和线程从操作系统层面理解实际就是 CPU 分配的时间片,当一个任务的时间片用完后,就需要切换到另一个任务。举个例子:CPU 对 任务1 和 任务2 分别分配了各自的占用时间:任务1时间片用完后,CPU 保存任务1的状态方便下次接着运行任务2占用CPU,CPU加载任务2的状态,接着上次停顿的点运行这里任务的状态实际就是上下文,上下文包含寄存器和程序计数器的内容,也就是代码运行的地址和操作数上下文切换就是保存和切换的过程。这里有更官方的名词

2021-06-08 17:28:00 507

原创 快速排序及优化

冒泡排序和快速排序都属于交换排序,其中快排更像是冒泡的进化版本,我们先看冒泡排序:思想:每轮循环将本轮最大元素移动到数组末尾,以此类推,直到长度为一。假设数组长度为 n,第一轮循环将最大元素移动到下标为 n-1 的位置,第二轮需要判断前 n -1 个元素,并将最大元素移动到 n-2 的位置,以此类推。计算最大值通过比较交换完成。private void sort(int[] a) { // 长度为 n 的数组需要 n-1 轮循环 for (int i = 1; i <= a.length

2021-06-08 16:51:26 95

原创 Redis 持久化策略

常见的 Redis 持久化策略有以下四种:RDB:指定时间间隔生成数据集的时间点快照AOF:记录服务端执行的所有写操作命令,并在服务端启动时重新执行者部分命令还原数据集混合持久化:两者都使用,优先使用 AOF,因为 AOF 文件保存的数据相对更完整关闭持久化:保证 Redis 性能RDB:类似快照,在规定时间点将 Redis 在内存中的数据库信息保存到磁盘中,生成的 RDB 文件是压缩过的二进制格式RDB 文件可以通过以下 Redis 命令生成:SAVE:阻塞主进程,服务端暂时无法处理客户

2021-06-08 10:43:05 233

原创 Redis 内存淘汰策略

常见的过期清理策略有以下几种:定时删除:在设置键过期时间的同时,创建定时器,定时器在键过期时间来临时执行删除操作惰性删除:不考虑键的过期时间,只在每次获取键时,检查键是否过期。如果过期就删除,否则返回结果定期删除:每隔一段时间,程序对数据库进行一次检查,删除里面过期的键。具体删除多少键,检查多少数据由算法决定redis 使用惰性删除和定期删除,其中定期删除并不会每次扫描所有 key。假设现在保存了十万个包含过期时长的 key,如果每次清理全部遍历一遍的话,CPU 消耗太大,而且极有可能成为程序性

2021-06-04 16:44:49 119

原创 Java 阻塞队列

阻塞队列和普通队列主要区别在阻塞二字:阻塞添加:队列已满时,添加元素线程会阻塞,直到队列不满时才唤醒线程执行添加操作阻塞删除:队列元素为空时,删除元素线程会阻塞,直到队列不为空再执行删除操作常见的阻塞队列有 LinkedBlockingQueue 和 ArrayBlockingQueue,其中它们都实现 BlockingQueue 接口,该接口定义了阻塞队列需实现的核心方法:public interface BlockingQueue<E> extends Queue<E&gt

2021-06-02 15:30:32 136 1

原创 Java 线程常用方法

Java 线程常用方法有以下几种:Object 方法:wait()notify()notifyAll()静态方法:yield()sleep()currentThread()非静态方法:start()run()join()getState()interrupt()isInterrupted()

2021-06-01 15:52:32 431

原创 Condition 接口

Condition 是 AQS 为同步机制提供的升级,通过它增强了线程间的交互,其中它的源码如下:public interface Condition { // 使当前线程进入等待状态直到被通知(signal)或中断 void await() throws InterruptedException; // 使当前线程进入等待状态,直到被唤醒,该方法不响应中断要求 void awaitUninterruptibly(); // 使当前线程进入等待状态直到被通知(signal)或中断或超时 lon

2021-05-31 17:08:53 118

原创 ReentrantLock 可重入锁

Synchronized 被称为隐式锁,也叫 JVM 锁,因为它锁的持有和释放都是隐式的,无须开发者干预。Java 1.5 引入新的锁机制,其中锁的实现基于 Lock 接口:public interface Lock { // 加锁 void lock(); // 解锁 void unlock(); // 可中断获取锁,获取锁时可响应中断操作 void lockInterruptibly() throws InterruptedException; // 尝试非阻塞获取锁,能够获得返回tru

2021-05-31 10:44:46 236

原创 关于使用分布式锁仍无法解决线程安全问题

最近在项目开发时遇到线程安全问题,简单来说就是通过分布式锁防止多实例入库相同数据失败,不同实例还是会入库相同数据背景介绍:实例 A、B 接收完全相同的消息,经过加工后入库。为了防止同一份消息入库两次,A、B 采用分布式锁的方式保证同步,其中每条消息都包含唯一 id 字段,以该字段为 Key 建立分布式锁,假如 A 实例抢占到消息1的锁,执行入库并持有锁100秒不释放,在这100秒内当 B 系统扫描到消息1时,无法抢占锁,不执行入库。每条消息的入库都会封装为任务在线程池中执行,所以抢锁失败后不会二次扫描理

2021-05-24 10:20:01 374

原创 面向对象三大特性

继承、封装和多态继承:父子类之间,子类通过继承获得父类的某些属性和方法,使子类具备父类相同的行为。Java 只能继承一个类,通过 extends 关键字实现封装:将对象的属性封闭起来,不对外访问,对外只提供接口,防止对象属性被恶意篡改。对于调用者来说,只需调用方法即可,内部实现细节对它透明多态:对于统一行为,不同子类对象具备不同的表现形式多态存在的三个必要条件:继承重写父类声明指向子类对象简单来说,就是通过父类引用调用子类方法,不同子类可以有不同的实现。...

2021-05-13 22:02:07 61

原创 Redis 穿透、雪崩、击穿如何应对

缓存穿透描述:黑客故意使用非法参数查询,缓存中一定查不到,请求一定会打到数据库,数据库也不一定能查到,比如 id = -1。由于大量的恶意请求,数据库宕机解决方案:对参数进行判断,恶意请求直接封 ip每次缓存、数据库都没有查到的数据,写一个空值到缓存中,例如 set -1 NULL,设置过期时长,这样下次有相同的 Key 来访问时,在缓存失效前,都不会打到数据库使用布隆过滤器存储所有可能访问到的 Key,不存在的 Key 直接被过滤缓存雪崩描述:假设系统本身通过 redis 抵挡流量高峰

2021-05-13 17:06:28 91

原创 如何保证数据库和缓存数据一致

部分场景下,对于数据库中需要频繁访问的热点数据,会保存一份拷贝在 redis 缓存,提高查询效率,具体流程如下:对于查询操作,首先从缓存中查询,查到直接返回,否则从数据库查询,将查询结果保存在缓存中,然后返回对于更新操作,先修改数据库,再删除缓存上述流程的执行就需要保证数据库和缓存数据一致。这里每次更新操作后删除缓存的原因在于:部分场景下缓存中的数据是数据库数据加工后的结果,可能需要联合其它数据一起计算,因此暂时删除掉使用缓存的主要原因在于提高查询效率,数据库中的数据不一定都会查到,因此先删

2021-05-13 15:40:41 183

空空如也

空空如也

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

TA关注的人

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