我们有一个应用,就是用户和物品有一个关注关系,类pinterest,用户打开页面会展示大量的物品图片,每个图片上要有用户是否关注过的标记,请问如何架构后台能保证大量用户不断的关注,和更大量的“用户是否关注物品”的查询,以及如果保证一致性和容灾?
修改
按投票排序
按时间排序
2 个回答
看你的两种元素的量,以及两种元素间关系的量。通常的状况是一个稀疏矩阵。常见的做法无非是用 Redis,建两种类型的 key:
单个实例 Redis 本身的一致性问题和容灾外面有很多成熟方案了,请自行搜索,此处不再赘述。如果你有多个 Redis 实例的话,一致性的主要问题可能是要保证『用户 a 关注物品 b』这个事件能同时写入到用户 a 的 set 和物品 b 的 set (假如不在同一个实例的话)。可以自己做个简单的 append-only file log,出现异常时回放检查一遍即可。 定期 snapshot 备份。
- 【基于用户的】set 结构,key 是用户 id,元素是该用户关注的物品 id
- 【基于物品的】也是 set 结构,key 是物品 id,元素是关注该物品的用户 id
单个实例 Redis 本身的一致性问题和容灾外面有很多成熟方案了,请自行搜索,此处不再赘述。如果你有多个 Redis 实例的话,一致性的主要问题可能是要保证『用户 a 关注物品 b』这个事件能同时写入到用户 a 的 set 和物品 b 的 set (假如不在同一个实例的话)。可以自己做个简单的 append-only file log,出现异常时回放检查一遍即可。 定期 snapshot 备份。
凡心 赞同
谢谢邀请
从场景分析:1.两个实体间的多对多关联表。2.两个实体的膨胀速度都是非可控的,关系表极端情况下会是笛卡尔积,因此数据量巨大。3.页面级的加载速度,不能有太长耗时。
未知问题:1.每个物品的关注是否要在首页显示出总量(sum)。2.翻页情况是什么样的?3.是否允许关联关系有延迟?
综合以上场景,个人推荐nosql + 用户id垂直sharding的架构,mongodb和redis的数据结构应该都符合场景的需求,这样首先保证了数据的加载速度与一定时间范围内的扩展性(毕竟会有sharding也无法解决的一天)。其次,如果数据的读写为极高比(比如1:100+),可以考虑加入pagecache技术(不知道访问量实在无法评估具体策略)。当然,读写分离也是可以的,但是要在db层面解决这个问题,读写分离的好处可以把数据同步的操作放在db层面,而且通常现在的分布式存储都原生支持,效率还是可靠的(适量的节点,最多也就1-3s的延迟),总的来说,更推荐读写分离模式。
至于容灾,我不清楚系统的故障时间要控制在多久,但如果是常规互联网应用(支付宝那种就算金融+互联网了,对容灾时间的要求差距很大),依靠主备方案就可以了(数据同步层面由DB原生支持,出问题的时间主要是主库挂掉备库拉起来的时间)。
只是一个大概的架构思路,供参考,其实如果知道了确定的数据量,或许cache+mysql也是可以承受的,并且开发和维护成本较低。
从场景分析:1.两个实体间的多对多关联表。2.两个实体的膨胀速度都是非可控的,关系表极端情况下会是笛卡尔积,因此数据量巨大。3.页面级的加载速度,不能有太长耗时。
未知问题:1.每个物品的关注是否要在首页显示出总量(sum)。2.翻页情况是什么样的?3.是否允许关联关系有延迟?
综合以上场景,个人推荐nosql + 用户id垂直sharding的架构,mongodb和redis的数据结构应该都符合场景的需求,这样首先保证了数据的加载速度与一定时间范围内的扩展性(毕竟会有sharding也无法解决的一天)。其次,如果数据的读写为极高比(比如1:100+),可以考虑加入pagecache技术(不知道访问量实在无法评估具体策略)。当然,读写分离也是可以的,但是要在db层面解决这个问题,读写分离的好处可以把数据同步的操作放在db层面,而且通常现在的分布式存储都原生支持,效率还是可靠的(适量的节点,最多也就1-3s的延迟),总的来说,更推荐读写分离模式。
至于容灾,我不清楚系统的故障时间要控制在多久,但如果是常规互联网应用(支付宝那种就算金融+互联网了,对容灾时间的要求差距很大),依靠主备方案就可以了(数据同步层面由DB原生支持,出问题的时间主要是主库挂掉备库拉起来的时间)。
只是一个大概的架构思路,供参考,其实如果知道了确定的数据量,或许cache+mysql也是可以承受的,并且开发和维护成本较低。