calidion.github.io
calidion.github.io copied to clipboard
多账号体系下用户系统的设计
随着用户的社交关系越来越复杂,如何很好的管理用户的社交帐号成了大多数开发人员的头痛的事情。 下面我想探讨一下多账号体系下用户系统的设计。
要点
对于多帐号系统问题的关键在于以下几点:
- 为异构的社交帐号建立帐号体系
- 将异构的社交帐号统一到一个唯一的用户系统中来
- 解决同一个用户建立了多个用户帐号后的合并问题
解决方案
基于以上几个核心诉求,我们可以得到以下几个解决方案
1. 为支持的社交网络建立用户体系,从而可以得到各类用户表,比如
oauth-weibo, oauth-weixin, oauth-facebook,oaut- github. 由于这些社交网络的数据并不统一,所以不同的表格的格式不尽相同。 所以我们称之为异构数据。
2. 建立一张本地用户总表,用于存放唯一的用户数据
3. 为社交网络与本地用户建立对应关系,
建立如下的类型表:
本地用户唯一ID | 社交网络类型 | 社交网络唯一ID |
---|---|---|
1112 | 20 | |
5111 | 20 | |
6000 | weixin | 10 |
6000 | 300 |
也就是对于不同的weixin与qq用户,他们可能会共享一个本地唯一ID 6000
4. 如果用户通过社交网络登录时并没有创建帐号,可以自动创建一个唯一的用户ID
5. 合并帐号
很多时候用户可能会忘记他原来已经注册过帐号,所以同一用户会通过不同的登录方式登录进来。 到他发现自己两个帐号都在,并且不能统一到一个帐号下时一定很沮丧。 所以这个时候,你可以做一次帐号统一的工作。 具体很简单,将较完一点的唯一用户ID合并到较上一点的唯一用户ID上。 同时更新所有采用唯一用户ID的地方的信息,如果出现重复信息,删除较晚的用户信息。 为了安全起见,这些数据也可以放到固定的数据表里。
6. 这样不管用户出现过多少次重复,作一次合并就解决这些的问题。
请教一下唯一用户id规则怎么设定? 毕竟是不同社交账号,对应的id也不同
@soakit 不同的id放入不同的表里, 用一张用户表统一起来即可。
用户系统,主要分为账号体系和用户信息两大类。账号体系包括,登陆验证、注册、第三方授权、以及权限管理。用户信息包括,用户地理位置、用户属性、用户设备信息、还有用户日志信息。本文会介绍用户系统的具体落地方案。
登陆验证
在一般项目账号体系中,一般会要求支持手机、邮箱、账号、QQ、微信、微博实现登陆。后面三种方式都是基于第三方授权后,完成的身份验证。手机、邮箱、账号则是相对传统的登录方式。
用户身份与登录的授权方式是独立开的,即用户uid和登录方式是一对多的关系。举例来说,用户A在使用微博授权登陆后,服务端鉴别身份信息为uid=123。用户A下次使用微信登陆,服务端鉴别身份同样为uid=123。不存在同一用户A拥有多个账号信息的现象。
用户信息
用户信息,为便于扩展,分成两类。用户基础信息和用户拓展信息。基本信息用来保存用户的基本属性,年龄、性别、生日、头像、手机号码等。扩展信息,用来保存用户的设备信息或其他可扩展的内容。另外还有位置信息,这个可独立出来,也可合并到扩展信息中,根据自己的使用场景来定。
用户日志信息
日志信息,用来保存用户注册或者登陆行为的。另外会有一些修改密码或者修改重要信息的日志记录。
全局uid
建议不要使用表的主键作为用户ID,而是使用ID生成器(发号器)生成用户的唯一标示guid。当用户量急剧上升时,往往会采取分库分表的方法,然后通过将uid取余写到不同的表中。如果单纯的以某个表主键作为ID。会限制插入性能和增加业务复杂度,其次在分布式数据库中也无法保证ID唯一性。
全局ID生成,是有很多方案的。简单一点,可以采用redis自增属性,因为其具有原子性,在分布式坏境中,能保证ID的唯一性。另外还有其他的一些开源方案,可自行Google。
Access Token
与传统的Session相比,Access Token比较适合做RESTful Api开发。传统Web应用中,用户登陆后会写用户信息到cookie中,服务端通过Session就能得到用户的身份。
Access Token的是OAuth2.0中用户经过授权后,返回调用API的凭证。对于自己的应用来讲,用户在登录后,即返回accesstoken。在token有效期内可凭借此凭证,调用其他接口。对于accesstoken的刷新有两种方案,第一种每次用户重启app时,重新refresh。第二种,在调用周期内服务端发现access token可能过期时,返回新的token给客户端。
至于Access Token的生成,这个并没有规定,只要保证其唯一性即可。简单点,对用户uid和当前时间哈希得到新的Access Token,并设置过期时间。另外也可以采用JWT实现。
原文地址:http://gglinux.com/2017/03/31/user/
合并账号这方面做得显然不是很合理
合并账号不是仅仅合并用户表数据就好,所有设计到用户id的表都需要处理,如果遇到分库分表难度又更大。
这里讲的合并是一个最终的结果,过程如何处理不同的项目会有不同的方式。
但是如果一个用户合并后还存在多个用户ID,那么维护这些ID的成本将比合并的成本要高。
所以无论如何分库,分表了,你都需要统一ID。
除非你特别有资源,能够承担不合并ID的成本,那么不合并ID也不是不可以的。
所以分库,分表并不影响我所说的处理方式的合理性,正确性。同时也不影响其它方便处理的合理性。
我的处理方式只是一种合理的解决方案。
但是并不排除还存在其它正确的方案。
但是从简单性来讲,这种方案是相对比较简单的方案,也是一劳永逸的方案。
合并不是一个好的方法,可以参考qq关联账号来想,只要让用户绑定账号即可,数据还是分布在两个账号,不冲突。 如果单纯的要去将两个账号数据合并,操作比较麻烦。
另外关于账户表设计,上面推荐的是一张主表,外加一张三方表,我提供另一种方式: 比如:添加机构、学校、老师这些角色进来,用户单独存放在各自的表中,用户根据(表名和表ID)来确定唯一用户即可
如果你没有合并,显然各种操作的复杂度都会增加。
合并是一个时间点操作。
只要你的设计没有问题,合并完成后就不会有问题。
怎么会麻烦呢?
总比你以后搜索时因为帐户不同,搜索结果处理总是出错要简单多了。
同时QQ的帐户体系确实存在严重的问题,这一点阿里相比较而言要好很多。
阿里一个帐户基本上能将所有的服务走下来,QQ目前是不行。
这种不合并,不但会引起用户的不方便,更是会引起程序开发的不方便。
所以我不知道合并不好的说法怎么得出来的。
不能正常合并用户帐号,很显然是种设计缺陷。
"更新所有采用唯一用户ID的地方的信息" 这个操作不好实现与拓展。 很多表都关联了userId。还可能分布在多个数据库、甚至多个系统。 比如用户的商品、用户登录日志在mysql中。用户发布的作品,用户操作记录在mongodb中,用户浏览记录在redis中,而且这些数据的插入更新在不同的系统,有可能是java在操作商品数据库,有可能pyhon操作日志数据库,node操作博客数据库 然后以后还会新增需求,又会多一张关联用户id的表 这样合并起来,以后的拓展如何解决 在合并期间,分布式事务又如何解决 我现在这样的系统还能合并吗。。。
@SongJiaxin95
当你问这个问题的时候,说明你的能力需要提升了。
你这样的系统唯一要做的就是一开始就保持用户ID的唯一。
否则就需要做一次同步工作,不过这样的工作通常会以失败造终。