Greenplum UDP连接问题排查与解决

近日遇到Greenplum数据库执行部份SQL会卡住,最终报向某个节点发包失败的错误,此处记录一下排查过程和解决方法。

1. 故障现象

数据库状态正常,使用gpstate命令查看状态没有任何异常,可以正常进入数据库并查询任意表的数据,但是业务端反馈查询时一直卡住,没有数据。数据库错误如下:

2. SQL分析


获取实际执行的SQL后进行分解 ,最终定位到在在执行group by操作时会执行失败,取消group by则可以执行成功。对这两个SQL进行explain,分析查询计划,发现二者最大的区别在于加入了group by的SQL会有redistribution,而没有group by的SQL不存在redistribution。

包含group:

不包含group:

Redistribution需要各个segment之间的相互传输数据,根据之前的报错信息,判断可能是其他segment向172.28.0.148的segment发包失败。

3. 故障定位


数据库传输协议

Greenplum为保证效率,segment之间默认使用UDP连接。为确认相关信息,查看数据库参数gp_interconnect_type,该参数解释如下:
Greenplum UDP连接问题排查与解决_第1张图片使用以下命令查看当前连接协议:

gpconfig -s gp_interconnect_type

在这里插入图片描述
可以看出当前连接协议为UDP,尝试修改为TCP连接,命令如下:

gpconfig -c gp_interconnect_type -v tcp
gpstop -arf

修改为TCP连接后,再次执行业务SQL,可以执行成功,至此可以定位为UDP连接问题。

4. 问题解决


将数据库segment之间的UDP连接改为TCP连接可以修复查询失败的问题,但是理论上TCP连接的速度会低于UDP,为了保证数据库查询效率,需要修复在UDP连接下查询失败的问题。
关于UDP连接丢包的问题,可以参考这篇博文:
https://blog.csdn.net/wuyan6293/article/details/82191675
该文章中有较为详细的介绍,本文仅总结一下排查过程与解决方法。
1.确认UDP丢包信息
查询失败的报错信息中反复出现其他segment向172.28.0.148发包失败的信息,怀疑UDP发包到172.28.0.148节点后,该节点组包失败。可以在该节点使用netstat -s (statistic)命令查看各个协议的统计信息,该命令展示的信息较多,我们仅需关注Ip分类下的。

#netstat -s
Ip:
    1075974066 total packets received
    0 forwarded
    0 incoming packets discarded
    137873343 incoming packets delivered
    3803720 requests sent out
    48 dropped because of missing route
    1411 fragments dropped after timeout
    1072078860 reassemblies required
    133978164 packets reassembled ok
    239741 packet reassembles failed
    215 fragments received ok
    1720 fragments created

其中重点关注两个信息:

  • fragments dropped after timeout: 分片在reassemble buffer中超时后被丢弃的计数
  • packet reassembles failed: 报文重组失败计数。该值包含timeout的计数

如果
2.参数调整
1.fragments dropped after timeout场景
当fragments dropped after timeout数值异常时(是否异常可以参考其他节点,现场遇到的正常环境下是5位数,异常环境是10位数),需要调整的参数为net.ipv4.ipfrag_time。

# 检查一下该参数当前数值,内核默认值为30s
#cat /proc/sys/net/ipv4/ipfrag_time
30

# 动态调整 
#echo 60 >/proc/sys/net/ipv4/ipfrag_time
#或

#vi sysctl.conf  //如果没有该参数就追加
net.ipv4.ipfrag_time = 60  
#永久生效
#sysctl -p 

#检查是否修改成功
#cat /proc/sys/net/ipv4/ipfrag_time
#60

修改完该参数后可以尝试运行之前不能运行的SQL,如果还是失败,则继续修改下面的参数。

2.packet reassembles failed场景一
该场景下需要注意两个参数,ipfrag_high_thresh和ipfrag_low_thresh,参数简要介绍如下:

  • Linux 内核协议栈使用 reassemble buffer来缓存IP fragment
  • ipfrag_high_thresh 来配置buffer的最大值
  • 当buffer内存使用量达到最大值时,会丢弃buffer中的分片,直到空间降到 ipfrag_low_thresh 的值

需要增大这两个参数值来保证fragment在重组前不被丢弃,具体操作如下:

# 检查一下该参数当前数值
cat /proc/sys/net/ipv4/ipfrag_low_thresh
3145728
cat /proc/sys/net/ipv4/ipfrag_high_thresh
3355443

#将这两个数值增大10倍
# 动态调整 
echo 31457280 >/proc/sys/net/ipv4/ipfrag_low_thresh
echo 33554432 >/proc/sys/net/ipv4/ipfrag_high_thresh

#或

#vi sysctl.conf   //如果没有该参数就追加
net.ipv4.ipfrag_low_thresh=31457280
net.ipv4.ipfrag_high_thresh=33554430
#永久生效
#sysctl -p 

#检查是否修改成功
cat /proc/sys/net/ipv4/ipfrag_low_thresh
31457280
cat /proc/sys/net/ipv4/ipfrag_high_thresh
33554430

修改完该参数后可以尝试运行之前不能运行的SQL,如果还是失败,则继续修改下面的参数。

3.packet reassembles failed场景二
在网络发包的过程中,我们将接收端收到的IP分片依次排队标号,由于网络中有很多其他的流量,属于同一个UDP报文的两个相邻IP分片中间夹杂着其他报文的分片,如果它们编号差(距离)超过ipfrag_max_dist,会导致重组失败。 例如同一个UDP报文的相邻分片距离为95, 而ipfrag_max_dist值设置的小于95,就会造成该分片重组失败。该场景就会造成packet reassembles failed计数增加。需要增大ipfrag_max_dist值,操作如下:

# 检查一下该参数当前数值,一般默认为64
cat /proc/sys/net/ipv4/ipfrag_max_dist
64

#将这两个数值增大至96
# 动态调整 
echo 96 >/proc/sys/net/ipv4/ipfrag_max_dist

#或

#vi sysctl.conf   //如果没有该参数就追加
net.ipv4.ipfrag_max_dist=96
#永久生效
#sysctl -p 

#检查是否修改成功
cat /proc/sys/net/ipv4/ipfrag_max_dist
96

你可能感兴趣的:(Greenplum,Linux,udp,数据库,sql)