Java Cancer 实现心跳机制的数据同步框架

背景介绍

项目上需要用到一个类似与zookeeper的心跳加节点数据同步的功能,但由于项目上不使用zookeeper,便决定自己实现一套,以便以后有类似需求可以直接使用。
这是一个可以处理节点间心跳和基于心跳进行数据同步的框架,此框架重在心跳实现,如果要实现数据同步需要人工处理,下面会说明如何基于此框架实现数据同步。

数据流转图

数据同步流程

  • msgQueue: 预同步数据队列
  • receiveQueue: 已同步数据队列
  • ackMap: 消息确认机制

结构介绍

  • tonatyw.heart.cancer
    • base 实现协议需要继承的抽象类包,目前只实现了udp协议
      AbstractAgreement 协议抽象类

    • constants 常量类包
      Constants 常量类,存储一些文件路径和共用的字符串

    • handle 接收参数时的处理包

      • base 消息处理基类包
        BaseHandle 消息处理基类

      AckHandle 在发送方接收到接收方返回的回执消息时调用
      ReceiveHandle 在接收方接收到发送方发送的消息时调用

    • thread 线程包
      Receive 接收线程
      Send 发送线程
      StatusThread 节点状态更新线程

    • util 工具包
      HeartBox 心跳盒子,存储心跳期间需要使用的变量
      ProcessEngine 暂不用,留着
      Udp udp协议实现,udp心跳入口

数据流

image

  • msgQueue: 预同步数据队列
  • receiveQueue: 已同步数据队列
  • ackMap: 消息确认机制

使用

启动心跳

启动心跳线程前,需要将heartBox放在全局的地方,因为所有的信息都在于操作这一个对象,比如

public class Sets {
	private Sets(){}
	/** 心跳相关 */
	public static HeartBox heartBox = new HeartBox();
	/** 同步列表 结构为 标识->消息*/
	public static Map<String,Map<String,Object>> synMap = new HashMap<String,Map<String,Object>>();
}
int port = 8108;
String pIp = "127.0.0.1";
int pPort = 8191;
long timeout = 10000;
// 启动心跳线程
new Udp(ip, port, pIp, pPort, timeout, Sets.heartBox).begin();

如果没有父级

new Udp(ip, port, timeout, heartBox).begin();

数据同步

// 此步为数据同步需要,启动消息同步线程
new Thread(new MessageSynThread(Sets.heartBox)).start();

messageSynThread内容如下

/**
 * 消息同步线程
 * @ClassName MessageSynThread
 * @Description: 消息同步线程
 * @date 2019年6月12日 下午5:19:07
 */
public class MessageSynThread implements Runnable{
	/** 心跳相关信息 */
	private HeartBox heartBox;
	public MessageSynThread(HeartBox heartBox) {
		this.heartBox = heartBox;
	}
	@Override
	public void run() {
		// 轮询取同步消息
		while(true){
			try {
				/** 
				 	同步消息 分为三个字段 
					同步数据:data;
					同步数据类型:type -> task,resource;
				 	同步方式: method -> add update del
				*/
				// receiveQueue为当前节点接收到的同步消息
				String data = heartBox.getReceiveQueue().take();
				JSONObject json = JSON.parseObject(data);
				if(!Sets.synMap.containsKey(json.getString("type"))){
					Sets.synMap.put(json.getString("type"), new HashMap<String,Object>());
				}
				Map<String,Object> typeMap = Sets.synMap.get(json.getString("type"));
				try {
					Map<String,Object> dataMap = JSON.parseObject(json.getString("data"), new HashMap<String,Object>().getClass());
					ReflectUtil.processMethod(MessageSynHandle.class, json.getString("method"), typeMap,dataMap);
				} catch (Exception e) {
					e.printStackTrace();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

MessageSynHandle

/**
 * 数据同步操作
 * @ClassName MessageSynHandle
 * @Description: 数据同步操作
 * @author Tangjc
 * @date 2019年6月12日 下午7:54:07
 */
public class MessageSynHandle {
	/**
	 * 添加操作
	 * @Title: add
	 * @Description: 添加操作
	 * @author Tangjc
	 * @param synMap 同步集合
	 * @param dataMap 待同步数据
	 * @return void
	 */
	public void add(HashMap<String,Object> synMap,HashMap<String,Object> dataMap){
		synMap.putAll(dataMap);
	}
	/**
	 * 修改操作
	 * @Title: add
	 * @Description: 修改操作
	 * @author Tangjc
	 * @param synMap 同步集合
	 * @param dataMap 待同步数据
	 * @return void
	 */
	public void update(HashMap<String,Object> synMap,HashMap<String,Object> dataMap){
		synMap.putAll(dataMap);
	}
	/**
	 * 修改操作
	 * @Title: add
	 * @Description: 修改操作
	 * @author Tangjc
	 * @param synMap 同步集合
	 * @param dataMap 待同步数据
	 * @return void
	 */
	public void del(HashMap<String,Object> synMap,HashMap<String,Object> dataMap){
		dataMap.forEach((key,value)->{
			synMap.remove(key);
		});
	}
}

发送同步消息

在此心跳程序和同步线程启动好后,如果有需要同步的数据,请调出heartBox.getMsgQueueMap()

// 接收该同步消息的的ip 只有建立了心跳才能同步
String ip = "192.168.1.100"
JSONObject json = new JSONObject();
// 该此同步为 添加  除此之外还有update 修改,del 删除
json.put("method", "add");
// 标识 根据业务需要来 同步过去后变为 synMap的key
json.put("type", "resource");
// 数据 规定使用map格式
Map<String,String> dataMap = new HashMap<String,String>();
dataMap.put("userId",1);
json.put("data", dataMap);
// 根据ip选择需要同步的节点
Sets.heartBox.getMsgQueueMap().get(ip).put(json.toJSONString());

心跳线程会根据每一次心跳读取队列同步消息

接收同步消息

MessageSynThread同步线程里已经将ReceiveQueue的消息放入了synMap里这时候取出就好

String type = "resource"
Object userId = Sets.synMap.get(type).get("userId");

下一次更新计划

  • 基于用户实现数据同步
  • 增加http协议心跳同步
  • 修复bug(如果有- -)
    由于工作关系,看反响如何(如果有…),随缘更新

这里是git地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为你解答这个问题。 首先,让我们了解一下K-Means算法。K-Means是一种聚类算法,它可以将数据集分成K个不同的簇(cluster)。该算法的基本思想是: 1. 随机选择K个点作为簇的质心(centroid); 2. 对于每个数据点,计算它与所有质心的距离,将它分配到距离最近的簇中; 3. 对于每个簇,重新计算它的质心; 4. 重复2和3步骤,直到质心不发生变化或达到预定的迭代次数为止。 接下来,我们可以使用K-Means算法对breast cancer数据集进行聚类分析。这个数据集是一个经典的分类问题,其中包含了569个患者的肿瘤数据,每个数据点有30个特征。 我们可以使用Python中的scikit-learn库来实现K-Means算法。以下是实现代码: ```python # 导入库 from sklearn.datasets import load_breast_cancer from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler # 加载数据集 data = load_breast_cancer().data # 数据预处理 scaler = StandardScaler() data_scaled = scaler.fit_transform(data) # 运行K-Means聚类算法 kmeans = KMeans(n_clusters=2, random_state=0) kmeans.fit(data_scaled) # 打印聚类结果 print(kmeans.labels_) ``` 在上面的代码中,我们首先加载了breast cancer数据集,并使用StandardScaler进行数据预处理,然后运行K-Means算法,将数据集分成了2个簇。最后,我们打印了每个数据点所属的簇。 需要注意的是,我们在这里将K设置为2,因为数据集本身是一个二分类问题。在实际应用中,我们需要根据具体情况来选择K的值。 希望这个回答对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值