问题
用户数上升,服务要集群,如何实现主从机制,而且当主服务挂掉或停机维护时,其它任意从服务可自动变成主服务?java
程序猿A:这还不简单,用zookeeper就好了,配上Apache curator更方便,直接帮你实现好Leader Election了。git
程序猿B:嗯…zookeeper又要安装个服务,不想只为了这个主从又引入一个新东西,咱们已经有redis了,能不能基于redis来实现?github
答案是:yes。web
思路
开始前,先说一下基本的实现思路:redis
先有一个redisson的分布式锁RLock,名称为:leader-lock
全部服务在启动的时候都去尝试获取leader锁
获取锁成功的服务为主服务
未获取锁的其它服务为从服务
从服务每隔几秒钟一直去尝试获取leader锁,当主服务挂掉或停机时,其中一个从服务就会获取到锁变成主服务
码起来
分布式锁的初始化
RLock leaderLock = redissonClient.getLock(“leader-lock”);
ElectionThread
有了锁后,咱们须要一个专门的线程用于获取锁spring
class ElectionThread extends Thread {
private boolean isMaster = false;
public ElectionThread() {
setName("leader-election");
}
@Override
public void run() {
while (!stop) {
try {
if (isMaster) {
synchronized (masterLock) {
//leader锁获取到了,就不须要再去获取了,进入阻塞状态
masterLock.wait();
}
} else {
//全部从服务尝试获取leader锁,尝试并等待必定时间,若是未获取成功,就一直重试
isMaster = leaderLock.tryLock(WAIT_SECONDS, TimeUnit.SECONDS);
if (isMaster) {
//leader锁获取成功,当前服务为主服务
logger.info("got leadership");
}
}
} catch (InterruptedException e) {
}
}
}
//判断leader锁是否获取成功
public boolean isMaster() {
return isMaster;
}
}
tryHold
有了ElectionThread,须要提供一个方法启动它去获取锁api
public void tryHold(String leaderName) {
//分布式锁的初始化
leaderLock = redissonClient.getLock(leaderName);
//启动获取锁的线程
electionThread.start();
}
锁释放
锁获取到了,若是要释放怎么释放?ElectionThread须要加上释放锁的逻辑springboot
class ElectionThread extends Thread {
private boolean isMaster = false;
public ElectionThread() {
setName("leader-election");
}
@Override
public void run() {
while (!stop) {
try {
if (isMaster) {
synchronized (masterLock) {
//leader锁获取到了,就不须要再去获取了,进入阻塞状态
mas