use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.
the class ClusterNodeInformationParser method parse.
public ClusterNodeInformation parse(String nodeInfo, HostAndPort current) {
String[] nodeInfoPartArray = nodeInfo.split(" ");
HostAndPort node = getHostAndPortFromNodeLine(nodeInfoPartArray, current);
ClusterNodeInformation info = new ClusterNodeInformation(node);
if (nodeInfoPartArray.length >= SLOT_INFORMATIONS_START_INDEX) {
String[] slotInfoPartArray = extractSlotParts(nodeInfoPartArray);
fillSlotInformation(slotInfoPartArray, info);
}
return info;
}
use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.
the class RedisSentinelTest method testSentinel.
@Test
public void testSentinel() {
JedisSentinelPool sentinelPool = ClientBuilder.redisSentinel(appId).setConnectionTimeout(2000).setSoTimeout(1000).build();
HostAndPort currentHostMaster = sentinelPool.getCurrentHostMaster();
logger.info("current master: {}", currentHostMaster.toString());
Jedis jedis = sentinelPool.getResource();
for (int i = 0; i < 10; i++) {
jedis.lpush("mylist", "list-" + i);
}
jedis.close();
sentinelPool.destroy();
}
use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.
the class RedisClusterBuilder method build.
public JedisCluster build() {
if (jedisCluster == null) {
while (true) {
try {
lock.tryLock(10, TimeUnit.SECONDS);
if (jedisCluster != null) {
return jedisCluster;
}
String url = String.format(ConstUtils.REDIS_CLUSTER_URL, String.valueOf(appId));
String response = HttpUtils.doGet(url);
JSONObject jsonObject = null;
try {
jsonObject = JSONObject.parseObject(response);
} catch (Exception e) {
logger.error("remote build error, appId: {}", appId, e);
}
if (jsonObject == null) {
logger.error("get cluster info for appId: {} error. continue...", appId);
continue;
}
int status = jsonObject.getIntValue("status");
String message = jsonObject.getString("message");
/**
* 检查客户端版本 *
*/
if (status == ClientStatusEnum.ERROR.getStatus()) {
throw new IllegalStateException(message);
} else if (status == ClientStatusEnum.WARN.getStatus()) {
logger.warn(message);
} else {
logger.info(message);
}
Set<HostAndPort> nodeList = new HashSet<HostAndPort>();
// 形如 ip1:port1,ip2:port2,ip3:port3
String nodeInfo = jsonObject.getString("shardInfo");
// 为了兼容,如果允许直接nodeInfo.split(" ")
nodeInfo = nodeInfo.replace(" ", ",");
String[] nodeArray = nodeInfo.split(",");
for (String node : nodeArray) {
String[] ipAndPort = node.split(":");
if (ipAndPort.length < 2) {
continue;
}
String ip = ipAndPort[0];
int port = Integer.parseInt(ipAndPort[1]);
nodeList.add(new HostAndPort(ip, port));
}
// 收集上报数据
if (clientStatIsOpen) {
ClientDataCollectReportExecutor.getInstance();
}
String password = jsonObject.getString("password");
if (StringUtil.isBlank(password)) {
jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, jedisPoolConfig);
} else {
jedisCluster = new JedisCluster(nodeList, connectionTimeout, soTimeout, maxRedirections, password, jedisPoolConfig);
}
return jedisCluster;
} catch (Throwable e) {
logger.error(e.getMessage(), e);
} finally {
lock.unlock();
}
try {
// 活锁
TimeUnit.MILLISECONDS.sleep(200 + new Random().nextInt(1000));
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
} else {
return jedisCluster;
}
}
use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.
the class RedisDeployCenterImpl method addSlotsFailMaster.
@Override
public RedisOperateEnum addSlotsFailMaster(final long appId, int lossSlotsInstanceId, final String newMasterHost) throws Exception {
// 1.参数、应用、实例信息确认
Assert.isTrue(appId > 0);
Assert.isTrue(lossSlotsInstanceId > 0);
Assert.isTrue(StringUtils.isNotBlank(newMasterHost));
AppDesc appDesc = appDao.getAppDescById(appId);
Assert.isTrue(appDesc != null);
int type = appDesc.getType();
if (!TypeUtil.isRedisCluster(type)) {
logger.error("{} is not redis cluster type", appDesc);
return RedisOperateEnum.FAIL;
}
// 获取失联slots的实例信息
InstanceInfo lossSlotsInstanceInfo = instanceDao.getInstanceInfoById(lossSlotsInstanceId);
Assert.isTrue(lossSlotsInstanceInfo != null);
// 2.获取集群中一个健康的master作为clusterInfo Nodes的数据源
List<InstanceInfo> allInstanceInfo = redisCenter.getAllHealthyInstanceInfo(appId);
// InstanceInfo sourceMasterInstance = redisCenter.getHealthyInstanceInfo(appId);
if (allInstanceInfo == null || allInstanceInfo.size() == 0) {
logger.warn("appId {} get all instance is zero", appId);
return RedisOperateEnum.FAIL;
}
// 默认获取第一个master节点
InstanceInfo sourceMasterInstance = allInstanceInfo.get(0);
// 并未找到一个合适的实例可以
if (sourceMasterInstance == null) {
logger.warn("appId {} does not have right instance", appId);
return RedisOperateEnum.FAIL;
}
// 3. 找到丢失的slots,如果没找到就说明集群正常,直接返回
String healthyMasterHost = sourceMasterInstance.getIp();
int healthyMasterPort = sourceMasterInstance.getPort();
int healthyMasterMem = sourceMasterInstance.getMem();
// 3.1 查看整个集群中是否有丢失的slots
List<Integer> allLossSlots = redisCenter.getClusterLossSlots(appId, healthyMasterHost, healthyMasterPort);
if (CollectionUtils.isEmpty(allLossSlots)) {
logger.warn("appId {} all slots is regular and assigned", appId);
return RedisOperateEnum.ALREADY_SUCCESS;
}
// 3.2 查看目标实例丢失slots
final List<Integer> clusterLossSlots = redisCenter.getInstanceSlots(appId, healthyMasterHost, healthyMasterPort, lossSlotsInstanceInfo.getIp(), lossSlotsInstanceInfo.getPort());
// 4.开启新的节点
// 4.1 从newMasterHost找到可用的端口newMasterPort
final Integer newMasterPort = machineCenter.getAvailablePort(newMasterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER);
if (newMasterPort == null) {
logger.error("host={} getAvailablePort is null", newMasterHost);
return RedisOperateEnum.FAIL;
}
// 4.2 按照sourceMasterInstance的内存启动
boolean isRun = runInstance(appDesc, newMasterHost, newMasterPort, healthyMasterMem, true);
if (!isRun) {
logger.error("{}:{} is not run", newMasterHost, newMasterPort);
return RedisOperateEnum.FAIL;
}
// 4.3 拷贝配置
boolean isCopy = copyCommonConfig(appId, healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
if (!isCopy) {
logger.error("{}:{} copy config {}:{} is error", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
return RedisOperateEnum.FAIL;
}
// 5. meet
boolean isClusterMeet = false;
Jedis sourceMasterJedis = null;
try {
sourceMasterJedis = redisCenter.getJedis(appId, healthyMasterHost, healthyMasterPort);
isClusterMeet = clusterMeet(sourceMasterJedis, appId, newMasterHost, newMasterPort);
if (!isClusterMeet) {
logger.error("{}:{} cluster is failed", newMasterHost, newMasterPort);
return RedisOperateEnum.FAIL;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (sourceMasterJedis != null) {
sourceMasterJedis.close();
}
}
if (!isClusterMeet) {
logger.warn("{}:{} meet {}:{} is fail", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort);
return RedisOperateEnum.FAIL;
}
// 6. 分配slots
String nodeId = null;
Jedis newMasterJedis = null;
try {
newMasterJedis = redisCenter.getJedis(appId, newMasterHost, newMasterPort, 5000, 5000);
// 获取新的补救节点的nodeid
nodeId = getClusterNodeId(newMasterJedis);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (newMasterJedis != null) {
newMasterJedis.close();
}
}
final String newNodeId = nodeId;
if (StringUtils.isBlank(nodeId)) {
logger.warn("{}:{} nodeId is empty!");
return RedisOperateEnum.FAIL;
}
// 需要做setslot的实例列表
final List<HostAndPort> hostAndPorts = new ArrayList<>();
hostAndPorts.add(new HostAndPort(newMasterHost, newMasterPort));
for (InstanceInfo instance : allInstanceInfo) {
hostAndPorts.add(new HostAndPort(instance.getIp(), instance.getPort()));
}
final Map<String, Jedis> jedisMap = new HashMap<String, Jedis>();
for (final Integer slot : clusterLossSlots) {
logger.warn("set slot {} start", slot);
boolean setSlotStatus = new IdempotentConfirmer() {
@Override
public boolean execute() {
String setSlotsResult = null;
for (HostAndPort hostAndPort : hostAndPorts) {
Jedis masterJedis = null;
try {
String hostPort = hostAndPort.toString();
if (jedisMap.containsKey(hostAndPort)) {
masterJedis = jedisMap.get(hostAndPort);
} else {
masterJedis = redisCenter.getJedis(appId, hostAndPort.getHost(), hostAndPort.getPort(), 5000, 5000);
jedisMap.put(hostPort, masterJedis);
}
setSlotsResult = masterJedis.clusterSetSlotNode(slot, newNodeId);
logger.warn("\t {} set slot {}, result is {}", hostAndPort.toString(), slot, setSlotsResult);
} catch (JedisDataException exception) {
logger.warn(exception.getMessage());
// unkown jedis node
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
boolean nodeSetStatus = setSlotsResult != null && setSlotsResult.equalsIgnoreCase("OK");
return nodeSetStatus;
}
}.run();
// set slots result
if (setSlotStatus) {
logger.warn("set slot {} success", slot);
} else {
logger.warn("set slot {} faily", slot);
return RedisOperateEnum.FAIL;
}
}
// 统一关闭
for (Jedis jedis : jedisMap.values()) {
if (jedis != null) {
jedis.close();
}
}
// 7.保存实例信息、并开启收集信息
saveInstance(appId, newMasterHost, newMasterPort, healthyMasterMem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, "");
redisCenter.deployRedisCollection(appId, newMasterHost, newMasterPort);
// 休息一段时间,同步clusterNodes信息
TimeUnit.SECONDS.sleep(2);
// 8.最终打印出当前还没有补充的slots
List<Integer> currentLossSlots = redisCenter.getClusterLossSlots(appId, newMasterHost, newMasterPort);
logger.warn("appId {} failslots assigned unsuccessfully, lossslots is {}", appId, currentLossSlots);
return RedisOperateEnum.OP_SUCCESS;
}
use of redis.clients.jedis.HostAndPort in project cachecloud by sohutv.
the class JedisSentinelTestUtil method waitForNewPromotedMaster.
public static HostAndPort waitForNewPromotedMaster(final String masterName, final Jedis sentinelJedis, final Jedis commandJedis) throws InterruptedException {
final AtomicReference<String> newmaster = new AtomicReference<String>("");
sentinelJedis.psubscribe(new JedisPubSub() {
@Override
public void onPMessage(String pattern, String channel, String message) {
if (channel.equals("+switch-master")) {
newmaster.set(message);
punsubscribe();
} else if (channel.startsWith("-failover-abort")) {
punsubscribe();
throw new FailoverAbortedException("Unfortunately sentinel cannot failover... reason(channel) : " + channel + " / message : " + message);
}
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
commandJedis.sentinelFailover(masterName);
}
}, "*");
String[] chunks = newmaster.get().split(" ");
HostAndPort newMaster = new HostAndPort(chunks[3], Integer.parseInt(chunks[4]));
return newMaster;
}
Aggregations