疏漏总结(六)

  1. tcp如何解决粘包的

Tcp是一个流协议,本身是不具备包的特征的,换句话说,即使你send两次,recv一次,也不是因为tcp才导致是粘连,而是应用层协议的问题,tcp只能保证这个消息是按照顺序去发送的,而不控制粘包,粘包本身就不是tcp的特征。

  1. metaspace

metaspace可以说是在jdk8开始的一种新的概念,用来替换之前的持久代。在替换了之后关于Perm上的问题也就随之解决了,比如像是oom的问题,metaspace本意,就是元空间的意思,用来存储一些本地的方法类,一般情况下来说,我们都会把MaxMetaSpace的默认值设置为无穷大,一般也是为了让元数据区尽量不去发生gc,当然,这个值也是可以手动去调的。

那么,为什么不让他频繁发生gc呢,如果元数据区发生了gc,那么本地的一些类加载就会导致oom,同时也说明你所设置的内存大小不合适,需要更改。

  1. 逃逸分析

在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针。它涉及到指针分析和形状分析。

一般来说,逃逸分析都发生在JIT内,不会发生在静态编译内。
如果:
①对象被赋值给堆中对象的字段和类的静态变量。
②对象被传进了不确定的代码中去运行

就会被判定为逃逸。

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

当判断出对象不发生逃逸时,编译器可以使用逃逸分析的结果作一些代码优化
堆分配转化为栈分配。如果某个对象在子程序中被分配,并且指向该对象的指针永远不会逃逸,该对象就可以在分配在栈上,而不是在堆上。在有垃圾收集的语言中,这种优化可以降低垃圾收集器运行的频率
同步消除。如果发现某个对象只能从一个线程可访问,那么在这个对象上的操作可以不需要同步。
分离对象或标量替换。如果某个对象的访问方式不要求该对象是一个连续的内存结构,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。

  1. 方法区oom是为什么

方法区主要存储被虚拟机加载的类信息,如类名、访问修饰符、常量池、字段描述、方法描述等。理论上在JVM启动后该区域大小应该比较稳定,但是目前很多框架,比如Spring和Hibernate等在运行过程中都会动态生成类,因此也存在OOM的风险。
如果该区域OOM,错误结果会包含类似下面的信息:
java.lang.OutofMemoryError: PermGen space

  1. 垂直分表和水平分表

水平分割:

例:QQ的登录表。假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这100亿中查找,会很慢很慢。如果将这一张表分成100份,每张表有1亿条,就小了很多,比如qq0,qq1,qq1…qq99表。

垂直分割:

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

  1. String.intern()

这个方法是一个 native 的方法,但注释写的非常明了。“如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回”。

它的大体实现结构就是: JAVA 使用 jni 调用c++实现的StringTable的intern方法, StringTable的intern方法跟Java中的HashMap的实现是差不多的, 只是不能自动扩容。默认大小是1009。

  1. mysql索引下推()

若要查看此优化的工作原理,请首先考虑在不使用“索引条件下推”的情况下如何进行索引扫描:
1.获取下一行,首先读取索引元组,然后使用索引元组查找并读取整个表行。
2.测试WHERE 适用于此表的部分 条件。根据测试结果接受或拒绝该行。

当使用“索引条件下推”时,扫描将改为这样进行:
1.获取下一行的索引元组(而不是整个表行)。
2.测试WHERE 适用于此表的部分 条件,并且只能使用索引列进行检查。如果不满足条件,请转到下一行的索引元组。
3.如果满足条件,则使用索引元组来定位和读取整个表行。
4.测试WHERE 适用于此表的条件的其余部分 。根据测试结果接受或拒绝该行。

  1. redis io模型

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

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

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

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

  1. 进程调度策略

①先来先服务
②短作业优先
③时间片轮转
④高优先权优先调度
⑤高响应比优先调度算法
⑥多级反馈队列调度算法

  1. redis缓存删除策略

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

主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
当前已用内存超过maxmemory限定时,触发主动清理策略,策略包含以下几种:
1.volatile-lru(least recently used):最近最少使用算法,从设置了过期时间的键中选择空转时间最长的键值对清除掉;

2.volatile-lfu(least frequently used):最近最不经常使用算法,从设置了过期时间的键中选择某段时间之内使用频次最小的键值对清除掉;

3.volatile-ttl:从设置了过期时间的键中选择过期时间最早的键值对清除;

4.volatile-random:从设置了过期时间的键中,随机选择键进行清除;

5.allkeys-lru:最近最少使用算法,从所有的键中选择空转时间最长的键值对清除;

6.allkeys-lfu:最近最不经常使用算法,从所有的键中选择某段时间之内使用频次最少的键值对清除;

7.allkeys-random:所有的键中,随机选择键进行删除;

8.noeviction:不做任何的清理工作,在redis的内存超过限制之后,所有的写入操作都会返回错误;但是读操作都能正常的进行;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值