疏漏总结(三)

TCP如何解决粘包

tcp是基于流的协议,是没有边界的,本身也是不具有包的,粘包是应用层协议的问题,tcp只能保证每条数据按照顺序发送而不能控制粘包。

metaspace

JDK8开始将类的元数据放在本地内存中这个部分叫做MetaSpace元空间。这个区域在JDK7之前属于永久代,元空间和永久代都是存储class的相关信息包括class对象的Method,实际上元空间和永久代都是之前说的方法区的实现只是在实现上有些不同,因此说方法区只是一种JVM的规范,JDK8及之后版本中字符串常量池已经被移动到了Java堆中,使用元空间替换掉永久代

元空间和永久代最大区别在于:元空间使用本地内存,永久代使用的是JVM内存,使用本地内存最大的好处就是在JDK8及之后的版本中不会出现oom:PermGen space这个异常因为内存只会受到本地内存大小的限制。

JVM不会无限的使用本地内存是动态进行设置的。

MetaSpace比PermGen优势在于:

  1. 字符串常量存在永久代中,容易出现性能问题和内存溢出;
  2. 类和方法信息难以确定,给永久代的大小指定带来困难;
  3. 永久代会为GC带来不必要的复杂性,并且回收率很低;
  4. 元空间可以更加方便的将HotSpot与其他JVM如Jrockit集成。

逃逸分析

编译程序优化中,逃逸分析是一种确定指针动态范围的方法——分析程序哪些地方使用到指针,涉及到指针的分析和形状分析。

逃逸分析一般是发生在JIT Compiler内,不发生在静态编译内。

逃逸分析的情况:

  1. 对象被赋值给堆中对象的字段和类的静态变量
  2. 对象被传进不确定的代码中运行

第一种情况是因为对象放在堆中,其他线程可以进行访问,因此对象使用情况编译器无法进行追踪。
第二种情况是相当于JVM在解析普通字节码时候,没有发生JIT即使编译,编译器不能事先完整知晓这段代码将会对代码做些什么。

对象不会发生逃逸分析时候编译器就使用逃逸分析的结果对代码进行一些优化。
这个时候堆分配就会转化为栈分配。某个对象在子程序中被分配并且指向该对象的指针永远不会逃逸该对象就可以分配在栈中,存在垃圾收集的语言中这种优化可以降低垃圾收集器运行的频率。

同步消除:如果发现某个对象只能从一个线程访问,那么这个对象上的操作可不需要同步。

分离对象或标量替换:如果某个对象访问方式不要求对象是连续的内存结构那么对象的部分或者是全部都可以不存储在内存中而是存储在CPU寄存器中。

String.intern()原理

使用方式:

String s = new String("a");
s.intern();

intern是String自带的一个方法。

JDK6及之前调用intern方法时候如果字符串常量池先创建出该字符串对象返回池中的该字符串的引用,否则将此字符串对象添加到字符串常量池中并且返回该字符串对象的引用。

JDK6之后:调用intern方法时,如果字符串常量池先前已经创建出该字符串对象则返回池中的该字符串的引用,否则如果该字符串对象已经存在于Java堆中,则将堆中对此对象的引用添加到字符串常量池中并且返回该引用,如果堆中不存在则池中创建该字符串并返回其引用。

简单总结一下:JDK6之后不仅在池中加载字符串对象,还会在Java堆中加载一份字符串对象。

方法区OOM

方法区主要是存储被JVM加载的一些类信息,理论上JVM启动后该区域大小应该相对稳定,但是Spring在运行过程中会动态生成类,因此存在OOM的危险。

该区域发生OOM,错误信息会包含下面的信息:java.lang.OutofMemoryError: PermGen space

MySQL索引下推

查看优化工作原理,考虑不使用"索引条件下推"的情况下如何进行索引扫描:

  • 获取下一行,读取索引元组然后使用索引元组查找并读取整个表行
  • 测试where使用与此张表的部门条件,根据测试结果接收或者拒绝该行

使用”索引下推“时,扫描改为这样进行:

  • 获取下一行的索引元组(不是整行)
  • 测试where适用于此表的部门条件,并且只能使用索引列进行检查,不满足条件转到下一行的索引扫描
  • 满足条件,使用索引元组来定位和读取整个表行
  • 测试where适用于此表的条件的其余部门,根据测试结果接受或拒绝该行

垂直分表和水平分表

水平分表:
如果只有一张表,每个用户登录时候数据库都要从这些数据中进行查找速度会很慢,如果将表分成100份每份的数据就少了很多。

垂直分表:
垂直分表指的是表的记录并不多,但是字段去是很长的表占用的空间很大,检索表的时候需要执行大量的IO操作会严重降低性能,这个时候需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。

进程调度策略

1、先来先服务
2、短作业优先
3、时间片轮转
4、高优先权优先调度
5、高响应比优先调度算法
6、多级反馈队列调度算法

Redis IO模型

Redis本身采用的是Reactor模式去处理连接,就是每条连接都会占用一个文件描述符。

Redis底层不是用的BIO,实际上对于select和epoll进行一个封装,同时一个Redis内部对于二者模块的封装进行了宏定义,因为不同编译平台性能是不同的,Redis根据平台的特点和性能合理选择子模块,但是因为select函数是作为POSIX标准中的系统调用在不同版本的操作系统上都是会实现的,因此将其作为保底方案。

Redis优先选择时间复杂度O(1)的IO多路复用函数作为底层实现,包括Solaries 10中的evport、Linux的epoll和macOS中的kqueue,上述函数都是使用内核内部结构,并且能够服务几十万的文件描述符。

但是如果当前编译环境没有上述参数就会选择select作为备选方案,由于其在使用时扫描全部监听的描述符,因此其时间复杂度较差O(n),并且只能同时服务1024个描述符,因此一般不会以select作为第一个方案使用。

Redis缓存删除策略

被动删除:读/写一个已经过期的key时会触发惰性删除策略直接删除掉这个过期的key。

主动删除:由于惰性删除策略无法保证冷数据被及时删除因此Redis会定期主动淘汰一批已经过期的key。

当前已用内存超过maxmemory限定时候触发主动清理策略,策略包含下面几种:

  1. volatile-lru(least recently used):最近最少使用算法,从设置了过期时间的键中选择空转时间最长的键值对清除掉;
  2. volatile-ttl:从设置了过期时间的键中选择过期时间最早的键值对清除;
  3. volatile-random:从设置了过期时间的键中,随机选择键进行清除;
  4. volatile-lfu(least frequently used):最近最不经常使用算法,从设置了过期时间的键中选择某段时间之内使用频次最小的键值对清除掉;
  5. allkeys-lfu:最近最不经常使用算法,从所有的键中选择某段时间之内使用频次最少的键值对清除;
  6. allkeys-random:所有的键中,随机选择键进行删除;
  7. allkeys-lru:最近最少使用算法,从所有的键中选择空转时间最长的键值对清除;
  8. noeviction:不做任何的清理工作,在redis的内存超过限制之后,所有的写入操作都会返回错误;但是读操作都能正常的进行;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值