面试相关的问题(下)

四 Linux高级_

1.Linux机器 变慢,怎么查看?

(1)整机的性能

  • 主要查看的是CPU和内存

先查看整机的top,使用命令 top

Java基础面试相关-LMLPHP

虚拟机 使用1可以查看哪个核被占用过高

  • 查看id(上图中43.9id) 也就是空闲率

    • 越大越好,证明不是CPU引起的
  • COMMAND : 进程名称 PID 为对用的ID
  • load average 系统负载率
    • 上图中可见有三个值,3个数加起来/3 在乘以 100%,结果在>=60% 的话,说明系统负载很高

uptime,系统命令的精简版

Java基础面试相关-LMLPHP

(2)内存

查看内存命令 : free

Java基础面试相关-LMLPHP

命令 :

  • free : 单位为b(字节)
  • free -g :单位 为GB
  • free -m:单位为MB
  • free -h:以适于人类可读方式显示内存信息。-h与其他命令最大不同是-h选项会在数字后面加上适于人类可读的单位

Java基础面试相关-LMLPHP

(3)硬盘

命令df -h: 查看磁盘剩余空间数

Java基础面试相关-LMLPHP

(4)CPU

命令 : vmstat

  • vmstat -n 2 3:每2s采样一次,共计采样3次

Java基础面试相关-LMLPHP

Java基础面试相关-LMLPHP

  • us + sy :参考值为80%,如果us + sy >80%,说明可能存在CPU不足
  • id :处于空闲的CPU百分比
  • wa:系统等待IO的CPU时间百分比
  • st:来自于一个虚拟机偷取的CPU时间的百分比

(5)iostat(磁盘IO)

安装 apt-get install sysstat

iostat语法

用法:iostat [ 选项 ] [ <时间间隔> [ <次数> ]]

常用选项说明:

-c:只显示系统CPU统计信息,即单独输出avg-cpu结果,不包括device结果
-d:单独输出Device结果,不包括cpu结果
-k/-m:输出结果以kB/mB为单位,而不是以扇区数为单位
-x:输出更详细的io设备统计信息
interval/count:每次输出间隔时间,count表示输出次数,不带count表示循环输出

iostat,结果为从系统开机到当前执行时刻的统计信息

Java基础面试相关-LMLPHP

输出含义:

​ avg-cpu: 总体cpu使用情况统计信息,对于多核cpu,这里为所有cpu的平均值。重点关注iowait值,表示CPU用于等待io请求的完成时间。

​ Device: 各磁盘设备的IO统计信息。各列含义如下:

Device: 以sdX形式显示的设备名称
tps: 每秒进程下发的IO读、写请求数量
KB_read/s: 每秒从驱动器读入的数据量,单位为K。
KB_wrtn/s: 每秒从驱动器写入的数据量,单位为K。
KB_read: 读入数据总量,单位为K。
KB_wrtn: 写入数据总量,单位为K。

命令ostat -xdk 2 3 : 查看磁盘快设备分布

Java基础面试相关-LMLPHP

rrqm/s: 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并
wrqm/s: 每秒对该设备的写请求被合并次数
r/s: 每秒完成的读次数
w/s: 每秒完成的写次数
rkB/s: 每秒读数据量(kB为单位)
wkB/s: 每秒写数据量(kB为单位)
avgrq-sz:平均每次IO操作的数据量(扇区数为单位)
avgqu-sz: 平均等待处理的IO请求队列长度
await: 平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位)
svctm: 平均每次IO请求的处理时间(毫秒为单位)
%util: 采用周期内用于IO操作的时间比率,即IO队列非空的时间比率

重点关注参数

1、iowait% 表示CPU等待IO时间占整个CPU周期的百分比,如果iowait值超过50%,或者明显大于%system、%user以及%idle,表示IO可能存在问题。

2、avgqu-sz 表示磁盘IO队列长度,即IO等待个数。

3、await 表示每次IO请求等待时间,包括等待时间和处理时间

4、svctm 表示每次IO请求处理的时间

5、%util 表示磁盘忙碌情况,一般该值超过80%表示该磁盘可能处于繁忙状态。

2.小总结

top命令(整机)

可以查看进程的cpu占用率,和内存占用率。uptime 是top的精简版只看整机,不看各进程。

load average: 0.00, 0.00, 0.00 表示系统1分钟,5分钟,15分钟的负载值,如果三个数平均值大于0.6,说明系统负载较高。

vmstat(CPU):

例如vmstat -n 2 3 每2秒采样一次,采样3次

— proce r:表示运行和等待CPU时间片的进程数,原则上1核的运行队列不要超过2,整个系统的运行队列不能超过核数的2倍。b:表示等待资源的进程数,比如正在等待磁盘I/O,网络I/O等。

— cpu us:用户消耗CPU时间百分比,us值高,用户消耗CPU时间多,如果长期大于50%需要优化程序。 sy:内核消耗进程的CPU时间百分比。us+sy大于80%,说明可能CPU不足。

pidstat(CPU):

mpstat -P ALL 2 查看所有CPU核信息

pidstat -u 1 -p 进程号 查看进程使用CPU的用量分解信息

pidstat -p 进程号 -r 秒数 查看进程内存的占用率 每几秒采样一次

pidstat -d 2 -p 进程号 查看进程磁盘占用情况

free(内存):

free -m 查看系统内存单位M

df(硬盘):

df -h 查看硬盘占用空间

iostat(磁盘IO):

iostat -xdk 2 3 查看磁盘快设备分布

rKB/s wKb/s 表示每秒读写量,svctm I/O await I/O分别表示请求的平均服务时间和等待时间,单位毫秒 值接近说明没有等待磁盘性能好。

ifstat(网络IO):

ifstat 查看网络IO情况

CPU占用过高案例排查分析:

1 用top命令查找出CPU占比最高的进程 id

2 ps -ef 或者jps进一步定位,得知哪个后台程序

3 ps -mp 进程号 -o THREAD,tid, time 定位到具体线程

4 将需要的线程ID转换为16进制格式(英文小写格式)

5 jstack 进程ID | gep tid(16进制线程ID小写字母) -A60 查看线程出现问题的代码日志

五 分布式锁

1.分布式锁是什么

分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁就是保证这个房子只有一个门并且一次只有一个人可以进,而且门只有一把钥匙。然后许多人要去看书,可以,排队,第一个人拿着钥匙把门打开进屋看书并且把门锁上,然后第二个人没有钥匙,那就等着,等第一个出来,然后你在拿着钥匙进去,然后就是以此类推

分布式锁:在集群分布式环境,对多个JVM加锁

面试问题:

  • 你用过 redis 做分布式锁是吧,你们是自己写的工具类吗?(可以用 redission 做分布式锁)
  • 说说你用redis实现过分布式锁吗?如何实现的?你谈谈

2.zookeeper实现分布式锁

(1)分布式情况下,怎么解决订单号生成不重复?

问题产生

真分布式/伪分布式

分布式优缺点

解决

  • 使用分布式锁

    • MySQL数据库的乐观锁实现(不推荐,并发量不够)
    • redis ----redission
    • zookeeper
  • 提前生成好订单号,存放在内存中,获取订单号直接从内存中取

(2)实现思路

  • 设计思想
  • zookeeper临时节点的创建
  • zkClient端的事件监控通知

单线程的并发场景,我们可以使用synchronized关键之和ReentrantLock类等实现

对于分布式场景,我们使用分布式锁

创建锁 :多个jvm服务器之间,同时在zookeeper上创建相同的以个临时节点,因为临时节点路径是保证唯一,只要谁能创建节点成功,谁就能获取到锁.没有创建成功节点,只能注册个监听这个锁并进行等待,当释放锁的时候,采用事件通知给其他客户端重新获取锁的资源,这时候客户端使用事件监听,如果该临时节点被删除的话,重新进入获取锁的步骤.

释放锁:zookeeper使用直接关闭临时节点session会话连接,因为临时节点生命周期与session会话绑定在一块,如果session会话连接关闭的话,该临时节点也会被删除,这时候客户端使用事件监听,如果该临时节点被删除的话,重新进入到获取锁的步骤

3.Zookeeper 如何实现分布式锁

什么是临时顺序节点?通过临时有序节点实现分布式锁

Java基础面试相关-LMLPHP

Zookeeper 的数据存储结构就像一棵树,这棵树由节点组成,这种节点叫做 Znode。

Znode 分为四种类型:

  • 持久节点(PERSISTENT),类似持久化,数据要写到硬盘里

默认的节点类型。创建节点的客户端与 Zookeeper 断开连接后,该节点依旧存在。

  • 持久节点顺序节点(PERSISTENT_SEQUENTIAL)

所谓顺序节点,就是在创建节点时,Zookeeper 根据创建的时间顺序给该节点名称进行编号:

Java基础面试相关-LMLPHP

  • 临时节点(EPHEMERAL)

和持久节点相反,当创建节点的客户端与 Zookeeper 断开连接后,临时节点会被删除:

Java基础面试相关-LMLPHP

Java基础面试相关-LMLPHP

Java基础面试相关-LMLPHP

  • 临时顺序节点(EPHEMERAL_SEQUENTIAL)

顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper 根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与 Zookeeper 断开连接后,临时节点会被删除。

Zookeeper 分布式锁的原理

Zookeeper 分布式锁恰恰应用了临时顺序节点。具体如何实现呢?让我们来看一看详细步骤:

获取锁

首先,在 Zookeeper 当中创建一个持久节点 ParentLock。当第一个客户端想要获得锁时,需要在 ParentLock 这个节点下面创建一个临时顺序节点 Lock1。

Java基础面试相关-LMLPHP

之后,Client1 查找 ParentLock 下面所有的临时顺序节点并排序,判断自己所创建的节点 Lock1 是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。

Java基础面试相关-LMLPHP

这时候,如果再有一个客户端 Client2 前来获取锁,则在 ParentLock 下载再创建一个临时顺序节点 Lock2。

Java基础面试相关-LMLPHP

Client2 查找 ParentLock 下面所有的临时顺序节点并排序,判断自己所创建的节点 Lock2 是不是顺序最靠前的一个,结果发现节点 Lock2 并不是最小的。

于是,Client2 向排序仅比它靠前的节点 Lock1 注册 Watcher,用于监听 Lock1 节点是否存在。这意味着 Client2 抢锁失败,进入了等待状态。

Java基础面试相关-LMLPHP

这时候,如果又有一个客户端 Client3 前来获取锁,则在 ParentLock 下载再创建一个临时顺序节点 Lock3。

Java基础面试相关-LMLPHP

Client3 查找 ParentLock 下面所有的临时顺序节点并排序,判断自己所创建的节点 Lock3 是不是顺序最靠前的一个,结果同样发现节点 Lock3 并不是最小的。

于是,Client3 向排序仅比它靠前的节点 Lock2 注册 Watcher,用于监听 Lock2 节点是否存在。这意味着 Client3 同样抢锁失败,进入了等待状态。

Java基础面试相关-LMLPHP

这样一来,Client1 得到了锁,Client2 监听了 Lock1,Client3 监听了 Lock2。这恰恰形成了一个等待队列,

释放锁

释放锁分为两种情况:

任务完成,客户端显示释放

当任务完成时,Client1 会显示调用删除节点 Lock1 的指令。

Java基础面试相关-LMLPHP

任务执行过程中,客户端崩溃

获得锁的 Client1 在任务执行过程中,如果崩溃,则会断开与 Zookeeper 服务端的链接。根据临时节点的特性,相关联的节点 Lock1 会随之自动删除。

Java基础面试相关-LMLPHP

由于 Client2 一直监听着 Lock1 的存在状态,当 Lock1 节点被删除,Client2 会立刻收到通知。这时候 Client2 会再次查询 ParentLock 下面的所有节点,确认自己创建的节点 Lock2 是不是目前最小的节点。如果是最小,则 Client2 顺理成章获得了锁。

Java基础面试相关-LMLPHP

同理,如果 Client2 也因为任务完成或者节点崩溃而删除了节点 Lock2,那么 Client3 就会接到通知。

Java基础面试相关-LMLPHP

最终,Client3 成功得到了锁。

Java基础面试相关-LMLPHP

Zookeeper 和 Redis 分布式锁的比较

Java基础面试相关-LMLPHP

六MySQL高级

1.MyISAM和InnoDB对比

MySQL5.5,以后,MySQL开始使用InnoDB作为默认存储引擎

主外键不支持支持
事务不支持支持
行表锁表锁,即使操作一条记录也会锁住整个表.行锁,操作时只锁某一行,不对其他行有影响(适合高并发的操作).
缓存只缓存索引不缓存真实数据不仅缓存索引还要缓存真实数据,对内存要求高,而且内存大小对性能有决定性的影响
表空间
关注点性能事务
默认安装YY

2. 索引与数据处理

MySQL官方对索引的定义为: 索引(index)是帮助MySQL高效获取数据的数据结构,可以得到索引的本质: 索引是数据结构

可以简单的理解为"排好序的快速查找B+树数据结构"

  • B+树中的B代表平衡(balance)而不是二叉(binary)
  • 检索原理

我们知道,数据库查询是数据库的最主要功能之一,例如下面的SQL语句:

SELECT * FROM my_table WHERE col2 = '77'

可以从表“my_table”中获得“col2”为“77”的数据记录。

我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找(linear search),遍历“my_table”然后逐行匹配“col2”的值是否是“77”,这种复杂度为O(n)的算法在数据量很大时显然是糟糕的

好在计算机科学的发展提供了很多更优秀的查找算法,例如二分查找(binary search)、二叉树查找(binary tree search)等。如果稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织)

在数据之外,数据库系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构就是索引。

Java基础面试相关-LMLPHP

图中展示了一种可能的索引方式。左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在O(log2n)的复杂度内获取到相应数据。

3. MySQL索引结构

BTREE

  • B树(Balance Tree多路平衡查找树)
  • B+树(加强版多路平衡查找树)

为什么是B+树

Hash

时间复杂度为O(1) -->(不管有多少数据,查一次就能查到,最好的算法)-->数组

O(n)是最差的算法复杂度

加速查找速度的数据结构,常见有两类

  • 哈希,例如HashMap,查询/插入/修改/删除/的平均时间复杂度都是O(1)一次就搞定;
  • 树,例如平衡二叉搜索树,增删改查的平均时间复杂度都是O(log2(n));(log以2为底,n的对数),由于计算机为二进制,log2为底简写为log

可以看到,不管是读请求,还是写请求,哈希类型的索引,都要比树形的索引更快一些,那么为什么索引结构要设计成树形呢?

想想范围/排序等其他SQL条件:哈希型的索引,时间复杂度会退化为O(n)而树形的"有序"特性,依然能够保持O(log2(n))的高效率

InnoDB并不支持哈希索引,树稳定,O(log2(n))的高效率

普通二叉树

哈希(hash)比树(tree)更快,索引结构为什么要设计成树型

检索原理:二叉树的特点

  • 一个节点只能有两个子树,也就是一个节点度不能超过2
  • 左子节点小于(<)本节点,右子节点大于等于(>=)本节点,比我大的向右,比我小的向左

Java基础面试相关-LMLPHP

对该二叉树的节点进行查找发现:

  • 深度(高度)为1的节点的查找次数为1
  • 深度(高度)为2的节点的查找次数为2
  • 深度(高度)为N的节点的查找次数为N

结论:因此其平均查找次数为(1+2+2+3+3+3)/6=2.3次

那么有hash也能找到,但是hash无法解决排序和范围

问题

如果id的值是持续递增的话,会是什么样的结构?

Java基础面试相关-LMLPHP

Java基础面试相关-LMLPHP

平衡二叉树(AVL)

插入演示

结构图

Java基础面试相关-LMLPHP

树越高,遍历的次数也就越多,磁盘IO随着数据量的加大,导致系统性能能也会越来越慢

尽量要将树从瘦高变成矮胖

BTree

B树又叫二三树

插入演示

B树结构图

Java基础面试相关-LMLPHP

数据库索引为什么要用树结构来做存储? (InnoDB引擎使用的是B+树)

  • 1.树的查询效率高.
  • 2.可以保持有序

二叉查找树跟B数的时间复杂度都是O(logn),为什么使用的是B树,而不是二叉查找树?

磁盘I/O消耗比较小.(一颗完全二叉树的高度大约是logN,而一个完全M叉树的高度大约是logᴍN)

  数据库索引是存储在磁盘上的,索引的大小可能有几个G甚至更多.当我们利用索引查询的时候,不可能将整个索引全部加载到内存中,只能逐一加载每一个磁盘页,这里的磁盘页对应着索引树的节点.

结论;B树比平衡二叉树减少了一次IO操作

B+树

插入演示

B+树 结构图

Java基础面试相关-LMLPHP

图中可以看到,所有data信息都移动叶子节点中,而且子节点和子节点之间会有个指针指向,这个也是B+树的核心点,这样可以大大提升范围查询效率,也方便遍历整个树

非叶子节点不再存储数据,数据只存储在同一层的叶子节点上;

叶子之间,增加了链表,获取所有节点,不再需要中序遍历

数据库操作(4+2):增删改查+范围+排序

中序遍历首先遍历左子树,然后访问根节点,最后遍历右子树,若二叉树为空则结束返回,否则:

  • 中序遍历左子树
  • 访问根节点
  • 中序遍历右子树

Java基础面试相关-LMLPHP

中序遍历 : D B E A C F

结论

B+树是在B树基础上的一种优化使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+树实现其索引结构

B+树相对于B树 有几点不同

  • 非叶子节点只存储键值信息
  • 所有叶子节点之间都有一个链指针
  • 数据记录都存放在叶子节点中
04-23 08:58
查看更多