用户系统设计

简介: 注册、登录、查询、用户信息修改,哪个需求量最大?支持100M DAU。注册,登录,信息修改 QPS 约100M * 0.1 / 86400 ~ 1000.1 = 平均每个用户每天登录+注册+信息修改Peak = 100 * 3 = 300

1 系统分析


1.1 Scenario 场景

注册、登录、查询、用户信息修改,哪个需求量最大?


支持100M DAU。注册,登录,信息修改 QPS 约:


100M * 0.1 / 86400 ~ 100

0.1 = 平均每个用户每天登录+注册+信息修改

Peak = 100 * 3 = 300

查询QPS约


100 M * 100 / 86400 ~ 100k

100 = 平均每个用户每天与查询用户信息相关的操作次数(查看好友,发信息,更新消息主页)

Peak = 100k * 3 = 300 k

1.2 Service 服务

AuthenticationService 负责登录注册

UserService 负责用户信息存储与查询

FriendshipService 负责好友关系存储


1.3 Storage

QPS 与 常用数据存储系统。


MySQL、PosgreSQL 等 SQL 数据库性能约 1k QPS


MongoDB、Cassandra 等硬盘型NoSQL数据库性能约 10k QPS


Redis / Memcached 等内存型NoSQL数据库性能约100k ~ 1m QPS

(根据机器性能和硬盘数量及硬盘读写速度会有区别)


用户系统特点:读非常多,写非常少。读多写少的系统一定要使用 Cache 进行优化。


使用缓存,也就会带来数据不一致问题,数据库和缓存是两台机器,两套系统,并不支持加锁。如果是用一些第三方分布式锁,会导致存取效率降低,得不偿失。业界最常用的方法:


database.set(key, user);

cache.delete(key)

class UserService {


 def getUser(self, user_id):

  key = 'user::%s' % user_id

  user = cache.get(user)

  if user:

   return user

 

  user = db.get(user_id)

  cache.set(key, user)

  return user

 

 def setUser(self, user):

   key = 'user::%s' % user.id

   db.set(user)

   cache.delete(key)

}


并发情况下依旧会出问题,在getUser执行到如下两行之间时:


14.png


另一个进程执行setUser(),cache 里会放入旧数据


问题2:db set 成功,cache delete 失败


但这两种情况发生概率<< cache.delete + db.set。


解决一致性问题?

利用 cache 的 TTL。


任何一个 cache 中的 key 都不要永久有效,设置一个短暂有效时间,如 7 天。则即便在极低概率下出现数据不一致,也就最多不一致7天。即允许数据库和缓存有“短时”不一致,但最终一致。


如果写很多,咋办?

在每次数据修改的时候,会在 cache 中 delete 这个数据。若写多读少,则此时 cache 没有任何优化效果。


Authentication Service 登录系统


Session 会话

用户 Login 后,为之创建一个 session 对象

并把 session_key 返回给浏览器,让浏览器存储起来

浏览器将该值记录在浏览器的 cookie 中

用户每次向服务器发送的访问,都会自动带上该网站所有的 cookie

此时服务器拿到 cookie 中的 session_key,在 Session Table 中检测是否存在,是否过期

Cookie

HTTP 协议中浏览器和服务器的沟通机制,服务器把一些用于标记用户身份的信息,传递给浏览器,浏览器每次访问任何网页链接的时候,都会在 HTTP 请求中带上所有的该网站相关的Cookie 信息。Cookie 可理解为一个 Client 端的 hash table。


11.png


Session 记录过期以后,服务器会主动删除么?

只支持在一台机器登陆和在多台机器同时登陆的区别是什么?

Session 适合存在什么数据存储系统中


Friendship Service


好友关系的存储与查询


双向好友关系


单向好友关系

Twitter、Instagram、微博


存在 SQL 数据库时:


查询x所有的关注对象

select * from friendship where from_user_id=x


查询x所有的粉丝:


select * from friendship where to_user_id=x;


存在 NoSQL 数据库时:


Friendship:


10.png


双向好友关系

微信,Facebook,WhatsApp


方案一:存储为一条数据

select * from friendship where smaller_user_id = x or bigger_user_id=x  


为何区分 smaller / bigger?

SQL 可以按照这种方案,但NoSQL 很多不支持 Multi-index 不能使用这种方案。


方案二:存储为两条数据

select * from friendship where from_user_id=x


NoSQL 和 SQL 都可按照这种方案


你觉得哪种更好呢?


Cassandra

三层结构的 NoSQL 数据库


http://www.lintcode.com/problem/mini-cassandra/


第一层:row_key

第二层:column_key

第三层:value

Cassandra 的 Key = row_key + column_key,同一个 Key只对应一个 value


结构化信息如何存储?

将其他需要同时存储的数据,序列化(Serialize)到 value 里进行存储。


Serialization:把一个 object / hash 序列化为一个 string,比如把一棵二叉树序列化


http://www.lintcode.com/problem/binary-tree-serialization/


row_key

又称为 Hash Key, Partition Key。Cassandra 会根据这个 key 算一个 hash 值,然后决定整条数据存储在哪儿。无法 Range Query


常用:user_id


Column Key

insert(row_key, column_key, value)


任何一条数据,都包含上面三个部分。可指定 column_key 按何排序。


Cassandra 支持这样的“范围查询”:


query(row_key, column_start, column_end)


可以是复合值,如 timestamp + user_id


SQL vs NoSQL


SQL的column是在Schema中预先指定好的,不能随意添加

一条数据一般以 row 为单位(取出整个row作为一条数据)

NoSQL的column是动态的,无限大,可以随意添加


一条数据一般以 grid 为单位,row_key + column_key + value = 一条数据

只需要提前定义好 column_key 本身的格式(是一个 int 还是一个 int+string)

Cassandra 存储Friendship表


9.png


Cassandra 存储 NewsFeed

8.png



Friendship Table适合什么数据库?


SQL 和 NoSQL 的选择标准


原则1 大部分情况,都能用

原则2 需要支持事务,则禁选 NoSQL

原则3 想在什么地方偷懒,很大程度决定选什么数据库

SQL


结构化数据,自由创建索引


NoSQL


分布式,Auto-scale,Replica


原则4 一般一个网站会同时用多种数据库系统

不同的表单放在不同的数据库。


User Table 存在哪儿?

大部分公司选择了 SQL,因为信任度,Multi-Index!


Friendship 存在哪儿?

大部分公司选择了 NoSQL,因为数据结构简单,都是 key-value 的查询/存储需求,NoSQL效率更高!

目录
相关文章
|
2月前
|
存储 监控 安全
【软件设计师备考 专题 】设计系统功能:安全性策略和工作流
【软件设计师备考 专题 】设计系统功能:安全性策略和工作流
63 0
|
11月前
|
算法 前端开发 小程序
智能排班系统 【管理系统功能、操作说明——下篇】
智能排班系统 【管理系统功能、操作说明——下篇】
394 1
|
11月前
智能排班系统 【管理系统功能、操作说明——中篇】
智能排班系统 【管理系统功能、操作说明——中篇】
190 1
|
12月前
|
数据挖掘 网络架构
短链系统设计-服务设计
该系统其实很简单,只需要有一个 service即可:URL Service。由于 tiny url只有一个 UrlService: 本身其实就是个小的独立应用 也无需关心其他任何业务功能
112 0
短链系统设计-服务设计
|
存储 消息中间件 缓存
|
JSON uml 数据格式
设计系统
设计系统
112 0
设计系统
|
前端开发 安全 JavaScript
系统权限设计 - 推荐方案
在上篇文章《系统权限设计 - 基本概念和思路》中,介绍了我们在做权限设计的时候需要注意的一些点。
403 0
|
存储 SQL 开发框架
软件需求人员-如何提升需求分析和业务方案的能力
  今天我准备再写一篇软件需求人员能力提升方面的文章,也就是把这个问题进一步谈透。对于IT行业来说,前面谈到更多的是招聘软件开发或架构设计人员不容易,特别是架构人员也难以培养。而对于软件需求人员也是同样的道理。   软件需求不同于用户需求或原始需求,对于业务需求往往你无需任何的IT技术背景就能够提出你的需求和问题,而对于软件需求则涉及到业务需求分析,分解,形成完整的业务解决方案,复杂的还是涉及到业务建模,最终才形成软件需求。   因此软件需求人员实际是衔接业务用户和内部技术团队的关键桥梁,软件需求和业务建模做得好,技术实现本身也更加高效。同样,一个软件系统最终实现出来灵活,可复用,那么首先
476 0
|
存储 缓存 算法
系统设计系列之如何设计一个短链服务
短链服务的鼻祖是 TinyURL,是最早提供短链服务的网站,目前国内也有很多短链服务:新浪(t.cn)、百度(dwz.cn)、腾讯(url.cn)等等。
452 0
系统设计系列之如何设计一个短链服务
|
测试技术
第18章 系统功能设计
第III部分 项目综合实战 第18章 系统功能设计 18.1 系统整体功能结构 18.2 系统用例描述 18.3 主要功能流程描述
743 0