三个存储着相同数据的列表,如何同步效率比较高呢?

2019-03-27 05:19:36 +08:00
 lixyz

条件:

首先存储的列表字段有 id(String 类型) 和 status(只有 1 和 -1 两个状态,且状态只能从 1 修改为 -1,反之不行) 只有 id 和 status 都相同才算是同一个对象 如何保证三个数据库的数据一样呢?


因为数据库一个是手机日历,一个是手机 SQLite,一个是服务器 Mysql,所以也没有办法在数据库上想办法

想问下大伙儿,有更好的方法吗?我感觉我这个就是一个最基础的笨方法

我是这样做的,先拿 A 和 B 同步,保证 A\B 数据是一致的 再拿 A 和 C 做同步,当需要修改 A 的时候,同时也修改 B

大致代码是这样的:

public class Test {
	public static void main(String[] args) {
		HashMap<String, Bean> mapA = new HashMap<>(16);
		HashMap<String, Bean> mapB = new HashMap<>(16);
		HashMap<String, Bean> mapC = new HashMap<>(16);
		// A、B 两个数据库同步
		for (String key : mapA.keySet()) {
			if (mapB.containsKey(key)) {
				if (mapA.get(key).getStatus() != mapB.get(key).getStatus()) {
					if (mapB.get(key).getStatus() == 1) {
						// 将 B 数据库当中的 status 修改为 -1
					}
				}
			} else {
				// 将 mapA 中 key 对应的 value 插入到 数据库 B 当中
			}
		}
		for (String key : mapB.keySet()) {
			if (mapA.containsKey(key)) {
				if (mapB.get(key).getStatus() != mapA.get(key).getStatus()) {
					if (mapA.get(key).getStatus() == 1) {
						// 将 A 数据库当中的 status 修改为 -1
					}
				}
			} else {
				// 将 mapB 中 key 对应的 value 插入到 数据库 A 当中
			}
		}
		//以上操作保证了 A、B 两个数据库是同步的
		//然后再拿 A 和 C 两个数据库做同步
		//还是同样的逻辑,但是当需要修改 A 的数据的时候,同时也修改 B 数据库
		for (String key : mapA.keySet()) {
			if (mapC.containsKey(key)) {
				if (mapA.get(key).getStatus() != mapC.get(key).getStatus()) {
					if (mapC.get(key).getStatus() == 1) {
						// 将 C 数据库当中的 status 修改为 -1
					}
				}
			} else {
				// 将 mapA 中 key 对应的 value 插入到 数据库 C 当中
			}
		}
		for (String key : mapC.keySet()) {
			if (mapA.containsKey(key)) {
				if (mapC.get(key).getStatus() != mapA.get(key).getStatus()) {
					if (mapA.get(key).getStatus() == 1) {
						// 将 A 数据库当中的 status 修改为 -1
						// 将 B 数据库当中的 status 修改为 -1
					}
				}
			} else {
				// 将 mapC 中 key 对应的 value 插入到 数据库 A 当中
				// 将 mapC 中 key 对应的 value 插入到 数据库 B 当中
			}
		}
	}
}

class Bean {
	private String key;
	private int status;

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}
}
8847 次点击
所在节点    Android
15 条回复
yuikns
2019-03-27 07:50:01 +08:00
我理解日历和 sqlite 都是在本地?那么从结构上说,那么是有一些特别的查询必须用 sqlite 么?本地可以只取手机日历作为数据源么?
MoHen9
2019-03-27 08:44:24 +08:00
不太理解问题,但还是说一下吧,可以根据 ID 和 status 复写 entity 的 hashcode 和 equals 方法,这样 map 中的 A/B/C 三张表的数据只有一份被放在 HashMap 或 HashSet 中。
mooncakejs
2019-03-27 08:49:16 +08:00
多加一个 seq 字段,version 更新的时候顺便更新版本号。同步对比版本号就行
lixyz
2019-03-27 17:55:05 +08:00
@yuikns 使用场景是这样的
一个手机 APP,使用到了日历的功能,所以需要日历数据库,同时又添加了一些其他的功能,所以需要本机 SQLite,考虑到了有可能会更换手机,所以要讲数据上传到服务器,以便更换手机时同步数据,所以用到了 Mysql,三个数据库的字段是相同的,所以需要确保三个数据库数据是同步的
lixyz
2019-03-27 17:56:53 +08:00
@mooncakejs 添加版本号还需要修改数据库添加字段,可能是最后考虑的手段了
lixyz
2019-03-27 18:03:17 +08:00
@MoHen9 你的意思是将三个数据库的数据先全部存在一个 Map 当中,然后再拿这个 Map 依次和三个数据库做比较
之前想过这么做,但是存在一个问题,因为 Map 的 key 是不能重复的,所以 MapAll 只能存一条 ID,而这条 ID 的 status 有可能是 1 也有可能是 -1,那么在和 A B C 做比较的时候,还挺麻烦的,因为你需要确定 ABC 总是否包含 MapAll 的 key,还需要确定这个 key 对应的 Value 是不是相同,这么做好像没比我的方法简单多少。

不知道对于你的方法理解的是不是对的?
mooncakejs
2019-03-27 19:14:24 +08:00
@lixyz 那就写日志,把数据库的更新操作 append 到文件中,同步的时候替换掉 log 文件,从 log 回复数据
lixyz
2019-03-28 02:33:47 +08:00
@mooncakejs 哈哈哈哈这么操作更麻烦了。。。
thesharjah
2019-03-28 22:07:28 +08:00
怎么感觉题目有点悖论?
thesharjah
2019-03-28 22:09:53 +08:00
status 只能从 1 改为- 1,日历、sqlite、mysql 三个库,总会有主次对吧? 如果主的 status =- 1,次的 status = 1,请问如何保证三个数据库数据一致呢?
如果业务上不会出现这种场景,那么直接把主同步至次就是了
hayanami
2019-03-29 14:38:13 +08:00
同意楼上,你 A,B,C 三个库都是以 A 的数据为主,B,C 做从库定时同步就可以了。
而且你 mysql 是为了更换手机时同步数据,基本上使用量不大,没有必要即时同步。另外两个库可以通过异步操作,A 库数据变动,异步方法变动 B 库,或者数据库记录更新 log,B,C 可以根据 log 变更
lixyz
2019-03-31 18:34:36 +08:00
@thesharjah @hayanami
我没有给这三个数据库分主次
首先 APP 运行的设备肯定是随时联网的,所以在往这三个数据库保存数据的时候,会同时往这三个数据库插入相同的数据,修改(将 status 从 1 修改为 -1 )也是一样的同时进行
但有可能用户在点击了保存的时候网络突然出现了问题,或者是突然关机,这就有可能会导致本地 SQLite 或者 本地日历 或者云端 MySQL 数据没有保存(更新)成功
所以就需要在每次打开 APP 的时候检查一下是否有数据可以同步,并提醒用户进行同步
就按照上面的情形,没有办法确定哪一个数据库是主哪个是次
只需要保证每一个 ObjectId 都存在于 MySQL\SQLite\手机日历当中,并且他们对应的 status 也是相同的
lixyz
2019-03-31 18:35:38 +08:00
顶楼的代码做的就是分别拿每个数据库和其他两个数据库做比较,然后做出修改

但是我感觉有点儿太费劲了,所以想来请教一下有没有其他比较好的比较简单的方法
thesharjah
2019-04-01 14:46:09 +08:00
@lixyz 所以你设计的时候应该分主次,以某一个为主,另外两个为从库,写入数据时应该首先写入主,写入成功表示本次操作成功,写入失败则操作失败;操作失败可以有一套失败之后的流程,成功之后才是你需要考虑的同步的问题;此时同步就不会有 status 只能 1 改为- 1 的问题了,同步只是需要保证从库与主库一致,不需要关心任何业务逻辑关系
lixyz
2019-04-01 18:50:31 +08:00
@thesharjah 说的有道理。。。感谢感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/548944

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX