史上最全的 Linux 运维工程师面试题

Posted by Mike on 2020-05-17

Linux 基础知识篇

这一套题算是简单的,考的内容基本是 Linux 基本原理、查找命令、计划命令、防火墙设置等,以上这四点基本算是初级内容。

  1. 说说 Linux 启动大致过程?

加载 BIOS–>读取 MBR–>Boot Loader–>加载内核–>用户层 Init 依据 Inittab 文件来设定系统运行的等级(一般 3 或者 5,3 是多用户命令行,5 是图形界面)–>Init 进程执行 rc.syninit–>启动内核模块–>执行不同级别运行的脚本程序–>执行 /etc/rc.d/rc.local (本地运行服务)–>执行 /bin/login,就可以登录了。

基本看过 「鸟哥 Linux 私房菜」的就能知道,这是第五章管理员的第一个内容。

这道题可以扩展一下:Init 系统运行等级一共有几种,每一种都是什么?

0:关机,只要是0就不能开机
1:单用户模式,不能被远程登陆
2:多用户不能上网模式
3:多用户可以上网模式
4:未使用
5:有图形的 Linux
6:重启,只要是 6 就会不断的重启,子子孙孙无穷匮焉的重启

  1. Linux 系统是由那些部分组成?

Linux 由系统内核,Shell,文件系统和应用程序四部分组成。

  1. Apache 有几种工作模式,分别简述其工作模式及其优缺点?

Apache 主要有两种工作模式:Prefork (Apache 的默认安装模式)和 Worker( 可以在编译的时候添加 --with-mpm=worker 选项来指定)

Prefork 的特点是:预派生

  • 这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销
  • 可以防止意外的内存泄漏
  • 在服务器负载下降的时候会自动减少子进程数

Worker的特点是:支持混合的多线程多进程的多路处理模块

如果对于一个高流量的 HTTP 服务器,Worker MPM 是一个比较好的选择,因为 Worker MPM 占用的内存要比 Prefork 更小。

  1. 说说 LVS 三种工作模式的工作过程?

LVS 就是 Linux Virtual Server,Linux 虚拟服务器。

  • NAT (Network Address Translation) 模式。LB 收到用户请求包后,LB 将请求包中虚拟服务器的 IP 地址转换为某个选定 RS 的 IP 地址,转发给 RS;RS 将应答包发给 LB,LB 将应答包中 RS 的 IP 转为虚拟服务器的 IP 地址,回送给用户。
  • IP 隧道 (IP Tunneling)模式。LB 收到用户请求包后,根据 IP 隧道协议封装该包,然后传给某个选定的 RS;RS 解出请求信息,直接将应答内容传给用户。此时要求 RS 和 LB 都要支持 IP 隧道协议。
  • DR (Direct Routing) 模式。LB 收到请求包后,将请求包中目标 MAC 地址转换为某个选定 RS 的 MAC 地址后将包转发出去,RS 收到请求包后 ,可直接将应答内容传给用户。此时要求 LB 和所有 RS 都必须在一个物理段内,且 LB 与 RS 群共享一个虚拟 IP。
  1. 列出 Linux 常见打包工具并写相应解压缩参数(至少三种)?

Tar 命令就是打包工具,对应的解压缩参数 tar -cvf、 tar -zcvf、 tar -jcvf 是对应拆包解压什么文件的要对应记住,不要记混。

  1. 一个 EXT3 的文件分区,当用 touch 新建文件时报错,错误信息是磁盘已满,但是使用 df -H 查看分区信息时只使用了 50%,请分析具体原因?

两种情况:一种是磁盘配额问题,另外一种就是 EXT3 文件系统的设计不适合很多小文件跟大文件的一种文件格式,出现很多小文件时,容易导致 Inode 耗尽了。

  1. 请使用 Linux 系统命令统计出 establish 状态的连接数有多少?
1
$ netstat -an |grep ESTABLISHED |wc -l

netstat命令 -a 参数是显示所有链接,-n 是不要域名解析,即都是以数字 IP 的显示。

现实生产系统的时候,如果服务器维持的链接是成千上万的话,少用 netstat,多用 ss。

  1. 如何统计出一台 Web Server 上的各个状态(ESTABLISHED / SYN_SENT / SYN_RECV 等)的个数?
1
2
3
$ netstat -antl|grep ESTABLISTHED|wc -l
$ netstat -antl|grep SYN_SENT|wc -l
$ netstat -antl|grep SYN_RECV|wc -l

netstat 命令的 -t 参数是查询 TCP 协议的链接,-l 参数是查询 Listen 状态下的链接。

netstat -an 的话会出现大概三个部分的内容,一部分是 TCP 协议内容,一部分是 UDP 协议的内容,还有一部分是 Unix Socket 方面的链接,Active UNIX domain sockets (servers and established)。

  1. 查找 /usr/local/apache/logs 目录最后修改时间大于 30 天的文件并删除

find 命令以及相关搭配命令是笔试中的重点,因为在现实中运用的情况最多,所以必考必考必考!!!

1
$ find /usr/local/apache/logs -type f -mtime +30 -ok rm {} \;

使用 mtime +30 来描述修改时间大于 30 天,使用 -type -f 来描述文件,然后使用 -ok 命令将所有满足的文件都执行下一步操作。

这里是删除文件,所以比较人性化的用 ok,删之前询问一下,如果简单暴力就可以直接 -exec,直接枪毙掉。用了 -exec 的话是不用 -f 的,多此一举。

  1. 编写个 Shell 脚本将 /usr/local/test 目录下大于 100K 的文件转移到 /tmp 目录
1
2
3
touch AAA.sh
#!/bin/bash
find /usr/local/test/ -size +100K -exec mv {} /tmp \;

注:-exec and -ok 后面的花括号里面的内容就是使用 find 命令查找出来的文件名。

  1. 添加一条到 192.168.3.0/24 的路由,网关为 192.168.1.254?
1
$ route add -net 192.168.3.0 netmask 255.255.255.0 gw 192.168.1.254  或者  route add -net 192.168.3.0/24 gw 192.168.1.254

注:route 命令是临时性的增加路由,如果需要永久性的添加路由方法如下:

方法一

1
2
$ vim etc/rc.local
route add -net 192.168.3.0/24 gw 192.168.1.254。

方法二

1
2
$ vim etc/sysconfig/network 
GATEWAY=192.168.1.254
  1. 在每周 6 的凌晨 3:15 执行 /home/shell/collect.pl,并将标准输出和标准错误输出到 /dev/null 设备,请写出 crontab 中的语句?
1
15 3 * * 6 sh /home/shell/collect.pl  > /dev/null  2>&1

注:每一个命令的执行肯定都会有成功或者失败,系统默认 1 是 stdout 标准输出,2 是 stderr 标准错误,& 的含义是等同。2>&1 的意思就是将错误的信息重定向输出的地方跟 1 一样,都是去空设备文件。

  1. 在 11 月份内,每天的早上 6 点到 12 点中,每隔 2 小时执行一次 /usr/bin/httpd.sh 怎么实现 ?
1
2
$ crontab -e
1 6-12/2 * 11 * bash /usr/bin/httpd.sh

crontab、at 这种计划任务命令也是面试高频题目,crontab 一共有 5个 *,分别表示 “分钟”、“小时”,“日期”、“月份”、“星期几”。

基本的结构要明白,而且 “当大数有条件,小数任意” 的情况下,小数不要用 *,用 0 or 1。

如果这道题写成 * 6-12/2 * 11 * bash /usr/bin/httpd.sh,你的 Apache会很爽,它会在满足条件的情况下每一分钟都启动一下。

  1. 匹配 AAA 文本中的 key 并打印出该行及下面的 5 行?
1
$ grep -A 5 key AAA

注:-A 是查找关键词下面的行,-B 是查找关键词上面的行,-C 是上下的行,注意这里是 grep,而不是 find。

  1. 查询 AAA 文件里以 abc 结尾的行?
1
$ grep "abc$" AAA

注:这里不是 grep “abc$” | AAA,这里没有 “|” 的,要注意。

  1. 打印出 AAA 文件第 1 到第 3 行?
1
$ head -3 AAA

也可以用 sed 命令来实现

1
$ sed -n '1,3p' AAA
  1. 查询 AAA 里面空行的所在行号?
1
$ grep -n "^$" AAA

注意: grep -n 和 cat -n 这两个输出结果的区别。

  1. 利用 sed 命令将 test.txt 中所有的回车替换成空格?
1
$ sed -e "s/\n/ /g" test.txt

注:sed的 -e 参数是指多重编辑,也就是说可以 sed -e ... -e .... -e.... 一次性完成三个动作。

  1. 使用 ab 命令进行 100000 次请求,同时每秒 40 次并发的频率访问 http://www.123.com/AAA.txt
1
$ ab -n 100000 -c 40 http://www.123.com/AAA.txt

注: ab 命令是 Apache 自带的,同一个 IP 地址并发的访问网站的同一个内容其实是一个隐患。但是现在用路由器上网的情况满地走,所以优化网页的内容是码农的责任,但是适当的缩小准许并发范围是运维人员应该掌握的。

  1. 按照以下要求配置一个防火墙规则

a. 对所有地址开放本服务器的80端口、22端口、10~21端口。
b. 其他机器可以用ping命令来探测本服务器的链接情况
c. 其他没有被准许的端口将禁止访问

1
2
3
4
5
$ iptables -I INPUT -p tcp -dport 80 -j ACCEPT
$ iptables -I INPUT -p tcp -dport 22 -j ACCEPT
$ iptables -I INPUT -P tcp -dport 10:21 -i ACCEPT
$ iptables -I INPUT -p icmp -j ACCEPT
$ iptables -I INPUT -j REJECT

iptables 也是面试考察的一个重点内容。

iptables 的内容主要包括 “四表+五链”,不过具体问道哪四表哪五链的可能性很小,倒是这种结合实际情况直接让写一连串的规则考题蛮常见的。这道题很基础,写 iptables 有点在 CCNP 里写 ACL 控制访问列表的意思。

  1. top 和 ps 命令在进程占有资源率的统计方式有什么不同?

ps 命令是显示在执行 ps 这个命令时刻所有进程的情况,而 top 是动态的监控进程的情况。

top 命令显示系统总的统计信息,比如时间、CPU 情况、 内存状态和分区信息等等。

ps -ef 这个是一个比较常见的搭配方式,-e 是所有进程,-f 是文件之间的关系。

ps -aux 也是很常用的,意思是显示包含其他使用者的进程。ps 命令也可以搭配 -more 和管道符使用,也可以搭配输出重定向。

top -n 2 指的是更新两次之后就停;top -d 3 指的是更新周期是三秒;top -p 574 指的是显示 pid 为 574 的进程。top 状态下按 b 是显示高亮。

  1. inode 存储了哪些东西?目录名,文件名存在哪里?

inode 存储了文件大小、user id、group id、文件的读写执行权限、软连接硬链接被引用的次数、时间戳、block 的位置。唯独没有文件名!!!

目录名、文件名存在目录项里。

ls -i 这个是显示 inode 号码的查询方法。

stat 命令这个可以查询 inode 信息,使用方法为 stat AAA 即可。

  1. 如何查看 HTTP 的并发请求数与其 TCP 连接状态
1
$ netstat -n | awk '/^tcp/ {++b[$NF]} END {for(a in b) print a, b[a]}'
  1. 如何用嗅探 80 端口的访问最多的 IP
1
$ tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |head -10
  1. 如何查看当前系统每个 IP 的连接数
1
$ netstat -n | awk '/^tcp/ {print $5}'| awk -F: '{print $1}' | sort | uniq -c | sort -rn
  1. ps aux 命令中的 VSZ 代表什么意思? RSS 代表什么意思?

VSZ:虚拟内存集,进程所占用的虚拟内存的大小
RSS:实际内存集,进程所占用的实际内存的大小

  1. 符号链接与硬链接的区别

硬链接是复制,享用同一个 inode,不能跨分区,不能连目录,a 变 b 也变,但是 a 删 b 不删。
符号链接就是 -s,不享用同一个 inode,可以跨分区可以连目录,等于快捷方式。

28 如何检测并修复 /dev/hda5

1
$ e2fsck -p /dev/hda5

如果要求是检查 /dev/hda5 是否正常,如果有异常便自动修复,并且设定若有问答均回答[是],那么语句就是 e2fsck -a -y /dev/hda5

  1. 显示 /etc/inittab 中以 # 开头,且后面跟了一个或者多个空白字符,而后又跟了任意非空白字符的行
1
$ grep '^# \{1,\}[^ ]' /etc/inittab
  1. 显示 /etc/inittab 中包含了 : 一个数字 :(即两个冒号中间一个数字)的行
1
$ grep '\:[1-9]\{1\}\:' /etc/inittab
  1. 统计 /data/mysql 目录里的普通文件个数
1
$ find /data/mysql/ -type f|wc -l
  1. 写一个脚本,实现批量添加 20 个用户,用户名为 user1-20,密码为 user 后面跟 5 个随机字符
1
2
3
4
5
6
#!/bin/bash
#description: useradd
for i in `seq -f"%02g" 1 20`;do
useradd user$i
echo "user$i-`echo $RANDOM|md5sum|cut -c 1-5`"|passwd –stdinuser$i >/dev/null 2>&1
done
  1. 写一个脚本,实现判断 192.168.1.0/24 网络里,当前在线的IP有哪些
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
for ip in `seq 1 255`
do
{
ping -c 1 192.168.1.$ip > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo 192.168.1.$ip UP
else
echo 192.168.1.$ip DOWN
fi
}& #多进程启动
done
  1. 写一个脚本,判断一个指定的脚本是否是语法错误;如果有错误,则提醒用户键入 Q 或者 q 无视错误并退出其它任何键可以通过 vim 打开这个指定的脚本
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
read -p "please input check script->" file
if [ -f $file ]; then
sh -n $file > /dev/null 2>&1
if [ $? -ne 0 ]; then
read -p “You input $file syntax error,[Type q to exit or Type vim toedit]” answer
case $answer in
q | Q)
exit 0;;
*)
vim $file;;
esac
  1. 如何执行历史记录里的第 505 条命令
1
$ !505
  1. 文件系统 ext2、ext3、ext4 的区别是啥?

ext3 和 ext2 的主要区别在于 ext3 引入Journal。
ext2 和 ext3 的格式完全相同,只是在 ext 3 硬盘最后面有一部分空间用来存放 Journal(日志)的记录;
在 ext2 中,写资料到硬盘中时,先将资料写入缓存中,当缓存写满时才会写入硬盘中;
在 ext3 中,写资料到硬盘中时,先将资料写入缓存中,待缓存写满时系统先通知 Journal,再将资料写入硬盘,完成后再通知 Journal,资料已完成写入工作;
在 ext3 中,也就是有 Journal 机制里,系统开机时检查 Journal 的资料,来查看是否有错误产生,这样就快了很多;

ext4 和 ext3 的主要区别在于:首先 ext4 与 ext3 兼容,ext3 只支持 32000 个子目录,而 ext4 支持无限数量的子目录;ext3 所支持的 16TB 文件系统和最大的 2TB 的文件,而 ext4 分别支持 1EB(1,048,576TB,1EB=1024PB,1PB=1024TB)的文件系统,以及 16TB 的文件;ext3 的数据块分配策略是尽快分配,而 ext4 是尽可能地延迟分配,直到文件在 Cache 中写完才开始分配数据块并写入磁盘;ext4 允许关闭日志,以便某些有特殊需求的用户可以借此进一步提升性能等等等等。

  1. 如何杀死指定的进程?
1
$ ps -ef |grep 进程名 |grep -v grep|awk  '{print $2}' |xargs kill -9

注意:这里 awk 后面是单引号不是双引号。

Linux 服务器篇

  1. 请写出 Web 服务器的调优要点,以 Nginx 为例。
  • 尽可能的少用 HTTP,因为 HTTP 是有开销的;
  • 尽可能的使用 CDN;
  • 添加 Expire/Cache-Control 头,这个头是缓存用的,可以缓存图片和 Flash 那样不轻易更改的文件,减少访问时间;
  • 启动 Gzip 压缩,这个没啥好说的了;
  • 尽可能少的重定向,重定向是需要时间的,增加一次重定向就会多一次 Web需求;
  • 如果可以,把 Ajax也做缓存;
  • 减少 DNS 查询,很多网页会有外站的广告,这些广告也是会启动 DNS 查询的,所以如果不缺钱,减少这种广告;
  • 调好服务器里的 TCP 协议栈,这个无论是 Web 服务器还是应用服务器都是必须的;
  1. 编写一个 Nginx 的访问控制规则,要求只准许 192.168.3.29/24 、10.1.20.6/16 、34.26.157.0/24 这些机器访问,除此之外的机器不准许访问。
1
2
3
4
5
6
location/{
access 192.168.3.29/24;
access 10.1.20.6/16;
access 34.26.157.0/24;
deny all;
}
  1. 如何在 Nginx 中给 favicon.ico 和 robots.txt 设置过期时间。

这里为 favicon.ico 为 99 天,robots.txt 为 7 天并不记录 404 错误日志。

1
2
3
4
5
6
7
8
9
10
11
location ~(favicon.ico) {
log_not_found off;
expires 99d;
break;
}

location ~(robots.txt) {
log_not_found off;
expires 7d;
break;
}
  1. 如何在 Nginx 中设定某个文件的浏览器缓存过期时间为 600 秒,并不记录访问日志
1
2
3
4
5
location ^~ /html/scripts/loadhead_1.js {
access_log off;
expires 600;
break;
}
  1. 如何在 Nginx 中只允许固定 IP 访问网站,并加上密码。

设定账号是 james,密码是 123456。

1
2
3
4
5
6
7
printf "james:$(openssl passwd -crypt 123456)\n" >>/usr/local/nginx/conf/passwd
location \ {
allow 22.27.164.25; #允许的ipd
deny all;
auth_basic “KEY”; #登陆该网页的时候,会有这个“KEY”的提示,提示只能是英文,中文不识别。
auth_basic_user_file /conf/htpasswd;
}
  1. Web 服务器为 Nginx,如果访问服务器的 IP 地址是 203.46.97.124 的话,给他展现的主页是 /123.html,其他人就展现 index.html。
1
2
3
4
5
6
7
location / {
if ($remote_addr = 203.46.97.124 ) {
rewrite ^.*$ /123.html;
}
root /usr/local/nginx/html;
index index.html;
}
  1. 讲述一下 cookie 和 session 的区别

Cookie 机制采用的是在客户端保持状态的方案,而 Session 机制采用的是在服务器端保持状态的方案。

Cookie 不是很安全,别人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗,考虑到安全应当使用 Session。

Session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用 COOKIE。

单个 Cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 Cookie。

Cookie 如果没有设置生存时间,那么关闭浏览器的瞬间,Cookie 就会消失,下一次登陆依旧要输入账号密码,Cookie 默认是存储在硬盘里而不是内存里,如果是设置了生存时间,那么就会保存在内存里,下一次继续使用。

Session 有一个 Session ID,要是服务器能查询的到 ID,就会按这个 ID 号的内容体现数据,如果查询不到就会新建一个 ID,Session ID 是可以用 Cookie 的形式保存的。

  1. 写一个脚本自动备份 MySQL 并删除 30 天前的备份文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
#Description:Auto backup mysql
MYSQLDB=Test1
MYSQLUSR=Username
MYSQLPW=PASSWORD #定义账号、密码和需要备份的数据库名
BAKDIR=/data/backup/mysql/$(date +%Y-%m-%d)
if[ $UID -ne 0 ];then #UID是USERID的意思,0 是ROOT的ID号
echo This script must use administrator or root user ,please exit!
#提示当前账户不是ROOT,需要切换成ROOT用户
sleep 2
exit 0
fi

if [ ! -d $BAKDIR ];then
mkdir -p $BAKDIR
else
echo This is $BAKDIR exists ,please exit ….
sleep 2
exit
fi

/usr/bin/mysqldump -u$MYSQLUSR -p$MYSQLPW -d $MYSQLDB >/data/backup/mysql/`date +%Y-%m-%d`/www_db.sql
cd $BAKDIR ; tar -czf www_mysql_db.tar.gz *.sql
cd $BAKDIR ;find . -name "*.sql" |xargs rm -rf[ $? -eq 0 ]&&echo "This `date +%Y-%m-%d` RESIN BACKUP is SUCCESS"
cd /data/backup/mysql/ ;find . -mtime +30 |xargs rm -rf
  1. SELECT id,name FROM test1 和 SELECT id name FROM test1 这两个语句有什么区别?

第一个语句会出现两个列,第二个只有一个列,列的内容是 id 的内容,但是列的名称是 name,也就是说第二句话其实就是 “SELECT id AS name FROM test1”。

  1. 如果想把 test1 表格里满足 age 大于等于 30 的 username 都迁移到 test2 表格里的 username 列,需要什么命令?
1
INSERT test2(username) SELECT username FROM test1 WHERE age >=30;

注: 这种方法要注意,新表/旧表有更新的时候,旧表/新表不随之更新。因为没有链接,仅仅是一个一次性的复制而已。

  1. 列举出 A 表里满足价格 (price) 大于 A 表里所有货品平均价格的 id,name,age。
1
SELECT id,name,age FROM A WHERE > (SELECT AVG(price) FROM A)
  1. 请根据你的理解,简述负载均衡的实现方式

负载均衡主要分为两种:硬件(F5)和软件(NGINX、Haproxy、LVS),硬件效果比较牛逼,它是把 4-7 层的负载均衡功能做到一个硬件里面,但是价格昂贵最近用的越来越少了。
软件的负载均衡又分两种:四层和七层:四层是在 IP/TCP 协议栈上把网络包的 IP 地址和端口进行修改,达到转发的目的;七层就是在应用层里把 HTTP 请求、URL 等具体的应用数据发送到具体的服务器上。四层的效率比七层的高,四层一般安排在架构的前端,七层一般就是在具体服务器的前端。软件负载均衡比较常见的几个调度分配方式如下:

  • 轮询:访问请求依序分发给后端服务器;
  • 加权轮询:访问请求依序分发后端服务器,服务器权重越高被分发的几率也越大;
  • 最小连接数:将访问请求分发给当前连接数最小的一台后端服务器,服务器权重越高被分发的几率也越大。
  1. HTTP 一般是无状态的,怎么让它变成有状态的?

HTTP 协议跟 IP 协议、UDP 协议一样都是无状态的,HTTP 的无状态意思是每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况。补充一下,TCP 是有状态的,它的请求并不独立,它通过包头的一些控制字段来分别包的关系,这里可以自行脑补一下三次握手的图。

那么 HTTP 是无状态的这一点是无法改变的,那么要变得有状态,就需要引入 Cookie 和 Session,通过这两个机制去实现一个有状态的 Web 应用。用一个表达式可以这么理解:Web 应用 = HTTP 协议+ Session、Cookies 等状态机制+其他辅助的机制。

  1. 多进程和多线程的区别,你更喜欢用哪一个,为什么?

多进程:服务器每当接收到一个客户端信息的时候,从主进程里生成一个子进程与客户端建立连接开始交互,每一个子进程之间互相独立不受干扰,完成任务就收回资源,内存等也会被回收;
多线程:服务器每当接收到一个客户端信息的时候,从主进程里生成一个线程与客户端建立连接开始交互,多个线程位于同一个进程内,可以互相访问同样的内存等资源,彼此之间会有影响;

我个人更喜欢多进程,因为简单粗暴!

  1. LVS 脑裂如何解决,为什么会产生双 Master?

产生双 Master 的原因:1)服务器开启了 Iptables 防火墙,阻碍了心跳信息传输;2)服务器心跳网卡等信息写错了,导致心跳信息发送失败;3)心跳方式不搭配,心跳广播冲突;4)软件出 Bug 了;

要排除脑裂问题,第一步是检查 Iptables,很可能是由于 Iptables 把心跳信息隔断了,重要的话不说三遍也重要!

  1. 为什么 TCP 比 UDP 的信息更加可靠?详细说说 TCP 滑动窗口原理,窗口的大小如何确定。

TCP 可靠性由三个机制保证:1. 序号(TCP报文的序号)2. 确认(ACK机制)3. 重传(超时或者冗余的 ACK)

TCP 在传输的时候,因为接受方 B 能力有限,不可能一口气吃下所有发送方 A 所有的数据流信息,所以 B 要限制 A 每次发送的字节数量,并且一一确认,确认了之后 A 才可以继续发。这样的话,A 的在发送数据流的时候就会有四种形态:

1).已发送已确认;
2).已发送但没被确认;
3).未发送但是接受方已经准备好空间来接收;
4).未发送但是接受方尚未准备好空间来接收;

随着数据流的传输,这个形态是会时刻发生变化的,通过接受方 B 返回的确认信息来改变 2 的大小,同时 B 也会根据一次关于发送方A要发送多少字节确认自己的空间来改变 3 的大小。

  1. 简单说说 CDN 的工作原理?

CDN 的工作原理:通过权威 DNS 服务器来实现优质节点的选择,通过缓存来减少源站的压力。

IT界有个很有名的比喻,正向代理是找马云借钱,反向代理是给 10086 打电话,而反向代理就是 CDN 的实现原理雏形的一部分。

  1. 请描述 DNS 查询的过程,为什么要有 CNAME 而不是直接返回一个 CDN 边缘节点的 IP。

DNS 主要是基于 UDP 协议的。DNS 查询的过程以 www.taobao.com 为例:

  • 在浏览器键入 www.taobao.com,其实真正 DNS 协议里用到的是 www.taobao.com. 最后还有一个点,可能是因为美观等原因,一般都不显示;
  • 查询本地缓存(host 文件或者是浏览器的缓存)中有没有该域名对应的记录,有的话就直接用了;
  • 向运营商的 DNS 服务器发起 DNS 解析的请求,一般称运营商的 DNS 服务器为 Local DNS;
  • Local DNS 会查询本地的缓存,Local DNS 设置的缓存时间是有讲究的,过长过短都不好。
  • Local DNS 如果没有缓存,会把域名从右往左扫描,依次请求对应的服务器,例如对于域名 www.taobao.com.,先去问负责 . 的根域名服务器,就是传说中全球只有几台的那些服务器,他们会答复 .com 是谁管理的,然后 Local DNS 又去找管理 .com 的服务器(假设名字为 S1),去问问taobao.com是谁管,一般来说,在S1查到的记录是一条cname记录(阿里毕竟大公司,自己管理自己旗下的域名),然后就转到了阿里自己的DNS服务器上来了,一般称之为权威服务器;
  • 权威服务器是阿里自己建的,然后根据公司内部的一些配置查到 www.taobao.com. 对应的服务器是谁,返回一个IP地址;
  • Local DNS 缓存这个 IP 地址,并且回复浏览器;
  • 浏览器和对应的 IP 地址的服务器建立 TCP 连接,发送 HTTP 报文;

https://rorschachchan.github.io/images/cdnyuanli.png

DNS 查询过程图解

至于说为什么不返回 CDN 边缘节点 IP,是因为使用 CNAME 记录可以很方便地变更 IP 地址,毕竟服务商掌握着 IP 的生杀大权,哪一天需要换 IP 了,在这方面很不方便。

  1. 什么是乐观锁,什么是悲观锁?

悲观锁 Pessimistic Lock, 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁 Optimistic Lock, 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition 机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种。像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行 Retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

  1. 什么是脏读、不可重复读、幻读?

脏读又称无效数据的读出,是指在数据库访问中,事务 T1 将某一值修改,然后事务 T2 读取该值,此后 T1 因为某种原因撤销对该值的修改,这就导致了 T2 所读取到的数据是无效的。

不可重复读是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务 T1 读取某一数据,事务 T2 读取并修改了该数据,T1 为了对读取值进行检验而再次读取该数据,便得到了不同的结果。

幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

  1. 简述一下 A 记录与 NS 记录的区别
  • A 记录是名称解析的重要记录,它用于将特定的主机名映射到对应主机的 IP 地址上。你可以在 DNS 服务器中手动创建或通过 DNS 客户端动态更新来创建。
  • NS 记录此记录指定负责此 DNS 区域的权威名称服务器。
  • A 记录和 NS 记录的区别是,A 记录直接给出目的 IP,NS 记录将 DNS 解析任务交给特定的服务器,NS 记录中记录的 IP 即为该特定服务器的 IP 地址。
  • NS 记录优先于 A 记录,A 记录优先于 CNAME 记录。
  1. MySQL 的 BinLog 有几种形式?

MySQL 的 BinLog 有以下几种模式:

  • Statement Level模式

简介:每一条会修改数据的 SQL 都会记录到 Master 的 Bin-Log 中。Slave 在复制的时候 SQL 线程会解析成和原来 Master 端执行过的相同语句来执行。
优点:不需要记录每一行数据的变化,减少 Bin-Log 的日志量,节约 IO 以提高性能。因为他只记录在 Master 上所执行语句的细节,以及执行语句时候的上下文的信息。
缺点:很多新功能的加入在复制的时候容易导致出现问题。

  • Row Level模式

简介:日志中会记录成每一行数据被修改的模式,然后再 Slave 端在对相同的数据进行修改。
优点:在 Row Level模式下,Bin-Log中可以不记录执行的 SQL 语句的上下文相关的信息。仅仅只需要记录那一条记录被修改了。所以 Row Level 的日志内容会非常清楚记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特点情况下的存储过程,或 Function 以及Triggeer 的调用和触发无法被正确复制的问题。
缺点:所有执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,可能会产生大量的日志。

  • Mixed(前两种的混合模式)

根据执行的每一条具体的 SQL 语句来区分对待记录日志的形式,即 MySQL 决定什么时候写 Statement 格式的,什么时候写 Row 格式的 Binlog。

  1. 如何在线正确清理 MySQL 的 Binlog?
  • 手动删除方法
1
2
3
4
5
6
# 首先查看主从库正在使用的binlog文件名称 
show master(slave) status\G
# 删除之前一定要备份
purge master logs before'2017-09-01 00:00:00';
# 删除指定时间前的日志
purge master logs to'mysql-bin.000001';
  • 自动删除的方法
1
2
3
4
# 通过设置 binlog 的过期时间让系统自动删除日志
# 查看过期时间与设置过期时间
show variables like 'expire_logs_days';
set global expire_logs_days = 30;

Binlog 记录了数据中的数据变动,便于对数据的基于时间点和基于位置的恢复。但是也要定时清理,不然越来越大。

  1. 简述 MySQL 主从复制原理及配置主从的完整步骤。

MySQL 主从是一个异步过程(网络条件上佳的话,同步效果几乎是实时),原理就是从库得到主库的 BinLog,然后执行这个 BinLog 的内容,达到两边数据库数据一致的目的。具体工作步骤如下:

  • 主mysql服务器将数据库更新记录到binlog中,使用自己的log dump线程将binlog先读取然后加锁,再发送到从库,在从库当读取完成,甚至在发动给从节点之前,锁会被释放;
  • 当从库上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的binlog。I/O线程接收到主节点binlog dump进程发来的更新之后,保存在本地relay log中。
  • 从库此时还有一个SQL线程,它负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

https://rorschachchan.github.io/images/mysql-sock9.png

切记!在从库上使用 show slave status\G;看到结果里的 Slave_IO_Running:Yes 和 Slave_SQL_Running:Yes,才算是同步成功,两个 YES 缺一不可。

注意: MySQL 只读实例的 Binlog 日志是没有记录更新信息的,所以它的 Binlog 无法使用。

  1. 如何理解 MySQL 里最大连接数和请求数之间的关系

假设某个数据库的最大连接数是 1000,并不是指最多只能支持 1000 个访问。因为数据库与应用之间肯定会隔着中间件,这个中间件的连接池会管理链接,一般如果代码写的好、事物控制得当,一个事物完成连接会被连接池收回重复利用。所以不是说一个用户登录你的系统或网站就一直占用着,一个连接也可以包含多次请求。

  1. MySQL 出现 IOPS 过高,应该如何处理?

IOPS (Input/Output Operations Per Second),即每秒进行读写(I/O)操作的次数。IOPS 是指存储每秒可接受多少次主机发出的访问,主机的一次 IO 需要多次访问存储才可以完成。IOPS 过高比较普遍的原因是实例内存满足不了缓存数据或排序等需要,导致产生大量的物理 IO 或者是查询执行效率低,扫描过多数据行。

  1. Sort_Buffer_Size 是什么参数?设置它对服务器性能有何影响?

Sort_Buffer_Size 是一个 connection 级参数,在每个 connection 第一次需要使用这个 Buffer 的时候,一次性分配设置的内存。Sort_Buffer_Size 并不是越大越好,由于是 Connection 级的参数,过大的设置+高并发可能会耗尽系统内存资源。Sort_Buffer_Size 超过 256KB 的时候,MySQL 就会使用 mmap() 而不是 malloc() 来进行内存分配,导致性能损耗、效率降低。

如果列长度大于 max_length_for_sort_data 的参数值的话,iowait 会增加, 响应时间明显变长。此时通过 show processlist 查看,发现有很多 session 在处理 sort 操作,此时需要适当调大 max_length_for_sort_data 的参数值。

  1. 如何从 MySQL 全库备份中恢复某个库和某张表

主要用到的参数是 –one-database 简写 -o 的参数,举个例子:

全库备份

1
$ mysqldump -uroot -p --single-transaction -A --master-data=2 >dump.sql

只还原 erp 库的内容

1
$ mysql -uroot -pMANAGER erp --one-database <dump.sql

从全库备份中抽取出 t 表的表结构

1
$ sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `t`/!d;q' dump.sql

从全库备份中抽取出 t 表的内容

1
$ grep'INSERT INTO `t`' dump.sql
  1. 你们数据库是否支持 Emoji 表情,如果不支持,如何操作?

如果是 utf8 字符集的话,需要升级至 utf8_mb4 方可支持。

  1. mysqldump 备份时,-–master-data 选项的作用是什么?还用过其他的参数么?

–master-data 选项的作用就是将二进制的信息写入到输出文件中,即写入备份的 SQL 文件中。

  • –master-data=2 表示在 dump 过程中记录主库的 Binlog 和 Pos 点,并在 dump 文件中注释掉这一行;
  • –master-data=1 表示在 dump 过程中记录主库的 Binlog 和 Pos 点,并在 dump 文件中不注释掉这一行,即恢复时会执行;
  • –dump-slave=2 表示在 dump 过程中,在从库 dump,mysqldump 进程也要在从库执行,记录当时主库的 Binlog 和 Pos 点,并在 dump 文件中注释掉这一行;
  • –dump-slave=1 表示在 dump 过程中,在从库 dump,mysqldump 进程也要在从库执行,记录当时主库的 Binlog 和 Pos 点,并在 dump 文件中不注释掉这一行;

注意:在从库上执行备份时,即 –dump-slave=2,这时整个 dump 过程都是 stop io_thread 的状态。加了 --single-transaction 就能保证 innodb 的数据是完全一致的,而 MyIsam 引擎无法保证(因为 MyIsam 压根就不支持事务),要保证 MyIsam 引擎数据一致必须加 --lock-all-tables。

  1. 什么是数据库事务,事务有哪些特性?

一个数据库事务通常包含对数据库进行读或写的一个操作序列。它的存在包含有以下两个目的:

  • 为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

它的特性如下:

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

事务的原子性与一致性缺一不可。

  1. 数据表 student 有 id,name,score,city 字段,其中 name 中的名字可有重复,需要消除重复行,请写 SQL 语句。
1
select distinct name from student

注意:单独的 distinct只能放在开头,否则就报语法错误。

  1. 在 Nginx 中,如何使用未定义的服务器名称来阻止处理请求?
1
2
3
4
5
Server {
listen 80;
server_name " ";
return 444;
}

这里,服务器名被保留为一个空字符串,它将在没有主机头字段的情况下匹配请求,而一个特殊的 Nginx 的非标准代码 444 被返回,从而终止连接。

  1. Nginx 中如何实现 http 跳转 https?
1
2
3
4
5
6
server {
listen 80;
listen [::]:80; #支持ipv6
server_name www.test.com;
return 301 https://$server_name$request_uri;
}
  1. 在 Nginx 中如果想配置指定域为信任,其他的域名被排除,应该如何配置?
1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name b.com;
location /{
if ( $http_referer ~* (a.com|b.com|c.com) ) {
Access-Control-Allow-Origin: *
}
}
}

35 CDN 缓存命中率下降的因素有哪些?

  • 客户是否刷新过缓存?

如果刷新缓存,有可能会短时间表现命中率下降。特别说明下:CDN 的 URL 或者目录刷新是清除 CDN 缓存的动作(这个比较容易理解偏差)

  • 带宽是否突增?并且访问的都是新的 URL?

带宽突增或者访问的新 URL 较多,会导致 CDN 节点回源较多,命中率会表现有下降趋势。

  • 源站是否有新内容发布?

CDN 节点访问新内容,导致 CDN 节点回源较多,命中率会表现有下降趋势。

  • 源站是否出现过异常导致 5XX 和 4XX 增加,由于 5XX 和 4XX 不缓存,会表现命中率下降。

  • 源站的访问 URL 的 Header 参数,或者在 CDN 控制管理后台的缓存配置规则是否改变过?

缓存时长的调整,有可能会带来命中率的变化。

  1. Docker 的 exec 与 attach 命令有啥区别?

attach 开启一个和正在运行的进程交互的终端,如果该进程结束,原 docker container 的进程也会结束。
exec 可以开启多个终端实例,exec -i /bin/bash,由此可见 exec 其实是在运行中的容器中执行一个命令。

  1. Docker 的 CMD 与 ENTRYPOINT 命令有啥区别?

CMD 的命令会被 Docker run 里的命令覆盖,而 ENTRYPOINT命令不会。
如果要覆盖 ENTRYPOINT,则在 Docker run 里添加 --entrypoint 标签来覆盖即可。
如果 Dockerfile 里指定了 WORKDIR,那么无论是 CMD 还是 ENTRYPOINT 命令都是在这个 WORKDIR 目录里执行。

  1. Docker 的 kill 和 stop 命令有啥区别?

stop 是优雅退出,先发送 SIGTERM 信号,在一段时间之后(10s)再发送 SIGKILL 信号。Docker 内部的应用程序可以接收 SIGTERM 信号,然后做一些退出前工作,比如保存状态、处理当前请求等。
kill 是暴力退出,即发送 SIGKILL 信号,应用程序直接退出。

  1. 假设有一个 AAA 的容器,现在需要备份它的挂载卷 /DATA 里的数据,请问如何操作?
1
$ docker run --volumes-form A -v /tmp:/backup --name BACKUP ubuntu tar cvf /backup/A.tar /DATA

上面这个语句新建立一个叫 BACKUP 的容器,它与 A 容器挂载情况相同(即都是挂载 /DATA)同时将本地的 /tmp 挂载到容器的 /backup。在容器生成的时候,执行了tar cvf /backup/A.tar /DATA 将 DATA 文件夹的内容进行了打包,又由于 /tmp 已经与 /backup 挂载,所以就可以直接从宿主机上的 /tmp 里得到 A.tar 了。

参考文档

  1. http://t.cn/Ai93uIum
  2. http://t.cn/Ai91yzEt
  3. http://t.cn/Ai91tykl
  4. http://t.cn/Ai91x5ik
  5. http://t.cn/Ai91pxxs
  6. http://t.cn/Ai9r1DvO
  7. http://t.cn/Ai9douNc
  8. http://t.cn/Ai9dHvb9
  9. http://t.cn/Ai9dnJ2z
  10. http://t.cn/Ai9d1sJN