合 GreenPlum中的FTS故障检测原理
Tags: GreenPlum
简介
FTS(Fault Tolerance Serve)是GreenPlum中的故障检测服务,是保证GP高可用的核心功能。GreenPlum的Segment的健康检测及HA是由GP Master实现的,GP Master上面有个专门的进程–FTS进程,它可以快速检测到Primary或者Mirror是否挂掉,并及时作出Primary/Mirror 故障切换。如果FTS挂掉了,Master将会重新fork出来一个FTS进程。
FTS实现原理
GP Master上面的FTS进程每隔60s(时间可以配置)向Primary或者Mirror发送心跳包,Primary和Mirror收到心跳包后返回它们的当前状态,FTS进程心跳包的发送状态和Segment返回状态更新元信息和作出故障切换。因为Segment可能很多,为了加快检测速度,FTS是多线程的,默认16个线程。
实现检测方法的源码大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | while (!probeGetIpAddr(&probeInfo) || !probeOpenSocket(&probeInfo) || !probeMarkSocketNonBlocking(&probeInfo) || !probeConnect(&probeInfo) || !probeSend(&probeInfo) || !probeReceive(&probeInfo) || !probeProcessResponse(&probeInfo)) { probeClose(&probeInfo); if (retryCnt == gp_fts_probe_retries) { write_log("FTS: failed to probe segment (content=%d, dbid=%d) after trying %d time(s), " "maximum number of retries reached.", probeInfo.segmentId, probeInfo.dbId, retryCnt); break; } /* sleep for 1 second to avoid tight loops */ pg_usleep(USECS_PER_SEC); retryCnt++; //other code } |
Segment检测及故障切换
GP Master首先会检测Primary状态,如果Primary不可连通,那么将会检测Mirror状态,Primary/Mirror状态总共有4种:
- Primary活着,Mirror活着。GP Master探测Primary成功之后直接返回,进行下一个Segment检测;
- Primary活着,Mirror挂了。GP Master探测Primary成功之后,通过Primary返回的状态得知Mirror挂掉了(Mirror挂掉之后,Primary将会探测到,将自己变成ChangeTracking模式),这时候更新Master元信息,进行下一个Segment检测;
- Primary挂了,Mirror活着。GP Master探测Primary失败之后探测Mirror,发现Mirror是活着,这时候更新Master上面的元信息,同时使Mirror接管Primary(故障切换),进行下一个Segment检测;
- Primary挂了,Mirror挂了。GP Master探测Primary失败之后探测Mirror,Mirror也是挂了,直到重试最大值,结束这个Segment的探测,也不更新Master元信息了,进行下一个Segment检测。
参数配置
gp_fts_probe_threadcount
用来故障检测的线程数量,默认为16。
gp_fts_probe_interval
两次检测的时间间隔,默认为60s。如果一次检测时间使用10s,那么剩余50s将会sleep;如果超过60s,将会直接进入下一次检测。
gp_fts_probe_timeout
检测Segment超时时间,默认值: 20。
gp_fts_probe_retries
检测Segment失败重试次数,如果超过这个次数,将会认为当前节点挂掉,默认值: 5。
gp_segment_connect_timeout
Prmary和Mirror文件同步允许连接Mirror最大超时时间,如果达到这个超时时间,Primary将会认为Mirror挂掉了,默认值: 180s。
示例
例如,假设默认超时参数值为:
1 2 3 4 5 | [gpadmin@mdw ~]$ gpconfig -s gp_fts_probe_timeout Values on all segments are consistent GUC : gp_fts_probe_timeout Master value: 20s Segment value: 20s |
具有主要段的群集信息是:
1 2 3 4 5 6 7 8 9 | flightdata=# select * from gp_segment_configuration where role='p'; dbid | content | role | preferred_role | mode | status | port | hostname | address | replication_port | san_mounts ------+---------+------+----------------+------+--------+-------+----------+---------+------------------+------------ 1 | -1 | p | p | s | u | 4340 | mdw | mdw | | 2 | 0 | p | p | s | u | 43400 | sdw3 | sdw3 | 49340 | 3 | 1 | p | p | s | u | 43401 | sdw3 | sdw3 | 49341 | 4 | 2 | p | p | s | u | 43400 | sdw4 | sdw4 | 49340 | 5 | 3 | p | p | s | u | 43401 | sdw4 | sdw4 | 49341 | (5 rows) |
这ftsprobe
仅与主分段通信,而不与镜像通信。因此,在gp_fts_probe_timeout
是允许主分段响应主呼叫的时间。主段会联系镜像以了解其健康状况。
处理集群信息的FTS探测器正在端口上运行4340
是:
1 2 | [gpadmin@mdw ~]$ ps -ef | grep -i fts | grep 4340 gpadmin 16695 16687 0 Feb12 ? 00:00:00 postgres: port 4340, ftsprobe process |
通过要求主进程postmaster休眠来中断主段进程通信:
1 2 3 4 5 6 | [gpadmin@mdw ~]$ ssh sdw3 Last login: Tue Feb 17 10:45:54 2015 from mdw [gpadmin@sdw3 ~]$ ps -ef | grep 43400 | grep silent gpadmin 10769 1 0 Feb12 ? 00:00:05 /usr/local/greenplum-db-4.3.4.0/bin/postgres -D /data1/primary/fai_43400 -p 43400 -b 2 -z 4 --silent-mode=true -i -M quiescent -C 0 [gpadmin@sdw3 ~]$ kill -s SIGSTOP 10769 [gpadmin@sdw3 ~]$ |
在主机上时,FTS探测器有时会因参数而失败gp_fts_probe_interval
。打开strace
为了ftsprobe
过程。请注意ftsprobe
流程进入FUTEX WAIT
在这个特定的ping过程中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [gpadmin@mdw ~]$ strace -p 16695 Process 16695 attached - interrupt to quit select(0, NULL, NULL, NULL, {36, 403000} ) = 0 (Timeout) getppid() = 16687 lseek(12, 0, SEEK_END) = 32768 lseek(13, 0, SEEK_END) = 32768 clone(child_stack=0x2b2f68969230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f689699d0, tls=0x2b2f68969940, child_tidptr=0x2b2f689699d0) = 18012 clone(child_stack=0x2b2f689aa230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f689aa9d0, tls=0x2b2f689aa940, child_tidptr=0x2b2f689aa9d0) = 18013 clone(child_stack=0x2b2f689eb230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f689eb9d0, tls=0x2b2f689eb940, child_tidptr=0x2b2f689eb9d0) = 18014 clone(child_stack=0x2b2f68a2c230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68a2c9d0, tls=0x2b2f68a2c940, child_tidptr=0x2b2f68a2c9d0) = 18015 clone(child_stack=0x2b2f68a6d230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68a6d9d0, tls=0x2b2f68a6d940, child_tidptr=0x2b2f68a6d9d0) = 18016 clone(child_stack=0x2b2f68aae230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68aae9d0, tls=0x2b2f68aae940, child_tidptr=0x2b2f68aae9d0) = 18017 clone(child_stack=0x2b2f68aef230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68aef9d0, tls=0x2b2f68aef940, child_tidptr=0x2b2f68aef9d0) = 18018 clone(child_stack=0x2b2f68b30230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68b309d0, tls=0x2b2f68b30940, child_tidptr=0x2b2f68b309d0) = 18019 clone(child_stack=0x2b2f68b71230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68b719d0, tls=0x2b2f68b71940, child_tidptr=0x2b2f68b719d0) = 18020 clone(child_stack=0x2b2f68bb2230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68bb29d0, tls=0x2b2f68bb2940, child_tidptr=0x2b2f68bb29d0) = 18021 clone(child_stack=0x2b2f68bf3230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68bf39d0, tls=0x2b2f68bf3940, child_tidptr=0x2b2f68bf39d0) = 18022 clone(child_stack=0x2b2f68c34230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68c349d0, tls=0x2b2f68c34940, child_tidptr=0x2b2f68c349d0) = 18023 clone(child_stack=0x2b2f68c75230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68c759d0, tls=0x2b2f68c75940, child_tidptr=0x2b2f68c759d0) = 18024 clone(child_stack=0x2b2f68cb6230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68cb69d0, tls=0x2b2f68cb6940, child_tidptr=0x2b2f68cb69d0) = 18025 clone(child_stack=0x2b2f68cf7230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68cf79d0, tls=0x2b2f68cf7940, child_tidptr=0x2b2f68cf79d0) = 18026 clone(child_stack=0x2b2f68d38230, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x2b2f68d389d0, tls=0x2b2f68d38940, child_tidptr=0x2b2f68d389d0) = 18027 futex(0x2b2f689699d0, FUTEX_WAIT, 18012, NULL) = 0 |
gp_fts_probe_timeout
是故障检测过程的允许超时(ftsprobe
)在声明段关闭之前建立与段的连接。