Java集合框架
Java集合框架QueueQueue接口是Java集合框架中定义的一个接口,它代表了一个先进先出(FIFO)的队列。Queue接口继承自Collection接口,它定义了一组方法来操作队列中的元素。下面是Queue接口的一些主要方法和特性的详细解释:
添加元素
boolean add(E element): 将指定的元素添加到队列的末尾,如果成功则返回true,如果队列已满则抛出异常。
boolean offer(E element): 将指定的元素添加到队列的末尾,如果成功则返回true,如果队列已满则返回false。
移除元素
E remove(): 移除并返回队列头部的元素,如果队列为空则抛出异常。
E poll(): 移除并返回队列头部的元素,如果队列为空则返回null。
获取头部元素
E element(): 获取队列头部的元素,但不移除它,如果队列为空则抛出异常。
E peek():获取队列头部的元素,但不移除它,如果队列为空则返回null。
Queue接口还有一些其他方法,如clear()用于清空队列中的所有元素,contains(Object o)用于判断队 ...
TCP三次握手
TCP三次握手TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。三次握手的过程如下图:
一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态
客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。
服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号 ...
TCP基础
TCPTCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
头部格式控制位
ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定。
FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。
为什么需要 TCP 协议? TCP 工作在哪一层?
IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性
如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP 协议来负责。
因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
UDP 和 TCP 有什么区别呢?分别的应用场景是?UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的 ...
Redis持久化
持久化How Redis writes data to disk
RDB–Redis DataBaseRDB 持久性以指定的时间间隔执行数据集的时间点快照。
实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。**这个快照文件就称为RDB文件(dump.rdb)**,其中,RDB就是Redis DataBase的缩写。
自动触发手动触发Save在主程序中执行会阻塞当前Redis服务器,直到持久化工作完成执行save命令期间,Redis不能处理其他任务
BGSAVE(默认)
Redis会在后台异步进行快照操作,不阻塞快照同时还可以影响客户端请求,该触发方式会fork一个子进程由子进程复制持久化过程
Redis会使用当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就是允许主进程同时可以修改数据
lastsave可以获取最后一次成功执行快照的时间
优点
适合大规模的数据恢复
按照业务定时备份
对数据完整性和一致性要求不高
RDB文件在内存中的加载速度要比AOF快得多
缺 ...
存储引擎
存储引擎数据存储数据页在磁盘怎么存在MySQL中,实际负责存储和查询的模块称为存储引擎。不同的存储引擎,对数据的存储和读取方式是不同的。MySQL支持多种存储引擎,甚至可以为每张表单独设置不同的存储引擎
数据都是保存在磁盘中的,但是其处理是需要首先加载到内存的。从磁盘读取是非常耗时的IO操作,为了减少对磁盘的读取次数,InnoDB采用页而不是行的粒度来保存数据,也就是数据被分为若干页,然后以页为单位保存在磁盘中。InnoDB的页大小,一般是16KB
设置系统默认的存储引擎查看默认的默认存储引擎
123show variable like '%storage_engine%';#或SELECT @@default_storage_engine;
修改默认的存储引擎
如果在创建表的语句中没有显式指定表的存储引擎的话,那就会默认使用 InnoDB 作为表的存储引擎。如果我们想改变表的默认存储引擎的话,可以这样写启动服务器的命令行:
1SET DEFAULT_STORAGE_ENGINE=MyISAM;
或者修改my.cnf文件:
1234default-storage ...
MySQL日志
MySQL日志两大日志事务有4种特性:原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢?
事务的隔离性由 锁机制 实现。
而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。
REDO LOG 称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。
UNDO LOG称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。
有的DBA或许会认为 UNDO 是 REDO 的逆过程,其实不然。REDO和UNDO都可以视为是一种恢复操作,但是:
redo log:是存储引擎层(innodb)生成的日志,记录的是”物理级别”上的页修改操作,比如页号xx、偏移量yyy写入了’zzz’数据。主要为了保证数据的可靠性;
undo log:是存储引擎层(innodb)生成的日志,记录的是逻辑操作日志,比如对某一行数据进行了INSERT语句操作,那么undo log就记录一条与之相反的DELETE操作。主要用于事务的回滚(undo log记录的是每个修改操作的逆操作)和一致性非锁定读(undo lo ...
垃圾收集器
垃圾收集器串行回收默认被应用在客户端的Client模式下的JVM
评价GC的性能指标
吞吐量:运行用户代码的时间占总运行时间的比例(总运行时间:程序的运行时间+内存回收的时间)
垃圾收集开销:吞吐量的补数,垃圾收集所用时间与总运行时间的比例
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间
收集频率:相对于应用程序的执行,收集操作发生的频率
内存占用:Java堆区所占用的内存大小
快速:一个对象从诞生到被回收所经历的时间
重点关注:
吞吐量
暂停时间
吞吐量
吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
比如:虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%
这种情况下,应用程序能容忍较高的暂停时间(暂停次数少),因此,高吞吐量的应用程序有更长的时间基准,快速响应是不必考虑的
暂停时间
是指一个时间段内应用程序线程暂停,让GC线程执行的状态(STW)
例如,GC期间100毫秒的暂停时间意味着在这个100毫秒期间内没有应用程序线程是活动的
总结 ...
MySQL索引
索引索引的定义就是帮助存储引擎快速获取数据的一种数据结构,形象的说就是索引是数据的目录。
索引分类按数据结构从数据结构的角度来看,MySQL 常见索引有 B+Tree 索引、HASH 索引、Full-Text 索引。
每一种存储引擎支持的索引类型不一定相同,我在表中总结了 MySQL 常见的存储引擎 InnoDB、MyISAM 和 Memory 分别支持的索引类型。
索引类型
InnoDB
MyISAM
Memory
B+
YES
YES
YES
Hash
NO
NO
YES
Full-Text
YES
YES
YES
B+Tree 是一种多叉树,叶子节点才存放数据,非叶子节点只存放索引,而且每个节点里的数据是按主键顺序存放的。每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息,并且每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。
B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tre ...
CAS
CAS概述compareAndSet,也有(Compare And Swap的说法),它必须时原子操作
是由硬件指令集支持的原子操作,原子行是由CPU保证的,JVM只是封装了汇编调用,这个操作需要输入两个数值,一个旧值(期望操作执行的值)和一个性质,在操作期间先比较旧值有没有改变,如果没有发生变化,才交换成新值
JDK正式利用这些CAS指令,可以实现并发的数据结构,比如AtomicInteger等原子类
volatile:
获取共享变量时,为了保证该变量的可见性,需要volatile修饰
它可以用来修饰成员变量和静态变量,它可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作volatile变量都是直接操作主存的。即一个线程对volatile变量的修改,对另一个线程可见
**注意:**volatile仅仅保证了共享变量的可见性,让其他线程能够看到最新值,但不能解决指令交错问题(不能保证原子性)
CAS必须借助volatile才能读取到共享变量的最新值来实现“比较并交换”的效果
为什么无锁效率高
无锁情况下,即使重试失败,线程始终再高速运行,没有停歇,而syn ...
Java内存模型
概述目前CPU的处理速度与内存的读写速度不在一个数量级,所以需要在CPU和内存之间加上缓存,来进行提速,这样就呈现出了一种CPU-寄存器-缓存-主存的访问结
这种结构在单CPU时期运行得很好,但是当一台计算机中引入了多个CPU,就出现缓存之间数据一致性的问题
针对这个问题,出现了缓存一致性协议,主要就是为了解决多个CPU缓存之间的同步问题,CPU缓存一致性协议有很多。
Java内存模型
屏蔽了各种硬件和操作系统的内存访问差异,实现了让Java程序能够在各种硬件平台下都能够按照预期的方法来运行
每个工作线程都有自己独占的本地内存,本地内存中存储的是私有变量以及共享变量的副本,使用一定机制来控制本地内存和主存之间读写数据的同步问题。
更加具体一点,我们将工作线程和本地内存具象为thread stack,将主存具象为heap。‘
在Thread stack中有两种类型的变量
原始类型变量,比如(int,char等)存储在线程上
对象类型变量,引用(指针)本身存储在线程栈上,引用指向对象存储在堆上。
堆中存储对象本身,持有该对象引用的线程就能够访问该对象了
Java线程模型中Thread ...