用户系统设计

简介: 注册、登录、查询、用户信息修改,哪个需求量最大?支持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效率更高!

目录
相关文章
|
监控 安全 BI
组态软件的功能需求分析
组态软件的功能需求分析
|
5月前
|
安全 Java 数据安全/隐私保护
构建高效网站后台:权限管理系统设计与实现
【7月更文挑战第5天】在现代Web应用开发中,权限管理是后台系统不可或缺的一部分,它确保了系统的安全性与用户数据的隐私。良好的权限管理系统能够精细控制不同用户角色对功能模块及数据资源的访问权限,从而提升系统的灵活性和安全性。本文将深入探讨权限管理的基本概念、设计思路,并通过一个简单的代码示例展示如何在Web后台中实现基本的权限控制逻辑。
306 2
|
5月前
|
调度
系统分析与设计问题之在用户视角,定时任务框架设计需要关注什么
系统分析与设计问题之在用户视角,定时任务框架设计需要关注什么
|
5月前
|
数据库管理 Python
在停车场管理系统工程中,我们可能会涉及到硬件设计、软件编程、数据库管理、用户界面设计等多个方面
在停车场管理系统工程中,我们可能会涉及到硬件设计、软件编程、数据库管理、用户界面设计等多个方面
|
7月前
|
C++
车辆管理系统设计(C++)
车辆管理系统设计(C++)
58 2
|
7月前
|
存储 JSON 安全
用户登录注册系统的安全性设计
用户登录注册系统的安全性设计
173 4
|
存储 消息中间件 缓存
系统设计:从零用户扩展到百万用户
设计一个支持百万用户的系统是具有挑战性的,这是一段需要不断改进和不断提升的旅程。在本章中,我们将构建一个支持单个用户的系统,并逐渐扩展以服务于数百万用户。阅读本章后,您将掌握一些技巧,帮助您解决系统设计面试问题。
系统设计:从零用户扩展到百万用户
|
存储 缓存 前端开发
|
存储 消息中间件 缓存
系统设计基础理解下
《基础系列》
112 0
|
JSON uml 数据格式
设计系统
设计系统
162 0
设计系统
下一篇
无影云桌面