多节点定时任务的同步

背景现在有两个或以上的web节点,启动时,会查询数据库,根据数据库中配置的数据(cron表达式等)创建定时任务。由于期望一个任务定时只有一个节点执行,所以需要多个web节点间做master竞选,这个已经实现了,身为master的web节点会将定时任务发送给实际执行的worker节点执行,非master节点的web节点会跳过此定时任务。 然而,由于系统有个功能,用户可以在web页面对定时任务进...

发布于 technology

通过zookeeper实现主从(Master-slave)竞选

背景为了提高系统的健壮性,我们常常做出多节点负载均衡的设计,通过zookeeper注册和发现可用服务,调用端通过一定的负载均衡策略决定请求哪一个可用服务节点。 然后,在某些情况下,服务的调用并非由客户端发起,而是由这个服务自身发起。比如,一个服务可能存在一些定时任务,每分钟去操作一下数据库之类的。当系统只有一个容器时,不用考虑主从的问题,只管到时间了就执行。但如果系统是分布式的,一个服务可能同时运行在多个容器中,查询类的定时任务没有影响,但是某些定时任务每次只需要执行一次,没有区分主从的情况下,每个容器下的服务都会企图去执行,很可能会造成不可预料的结果。 所以,我们需要达到的目标是,服务能够判断自己是否是Master,如果是,则执行,如果不是,则不执行。同时,如果Master服务掉线(比如宕机了),那么某个容器里的slave服务能够自动升级为Master,并执行Master执行的任务。 基础 Zookeeper客户端可以创建临时节点并保持长连接,当客户端断开连接时,临时节点会被删除 Zookeeper客户端可以监听节点变化 实现 定义一个持久化节点/gzcb/master/services,此节点下的子节点为临时节点,分别代表不同的Master服务 Container_1中的服务AccountService,在启动时,在zookeeper中创建临时节点/gzcb/master/services/AccountService:1.0.0,节点的数据为192.168.99.100:9090。这代表,192.168.99.100:9090这个容器中的AccountService(版本为1.0.0)成功竞选为Master服务。Container_1中维护一个缓存,如果竞选成功,对应service:version置为true,否则置为false; Container_2中的服务AccountService,在启动时,也试图创建临时节点/gzcb/master/services/AccountService:1.0.0,但是会创建失败,返回结果码显示该节点已经存在。所以服务就知道已经有一个Master的AccountService(1.0.0)存在,它竞选失败。 Container_2会保持对该临时节点的监听,如果监听到该零时节点被删除,则试图再次创建(创建临时节点的过程就是竞选master的过程),创建成功,则更新缓存对应service:version为true,否则继续保持监听。 优化不管竞选成功还是失败,可以维护一份Master缓存信息,并保持监听,实时更新。这样,不仅能够自动竞选master,还能够通过修改临时节点数据的方式,手动指定Master。 关键代码

发布于 technology