数据库扩展
QPS, 单点故障使得数据库必须要进行扩展. 扩展只需要做两件事情, 数据拆分 Sharding, 数据复制 Replica. 数据拆分可以分摊写流量, 数据复制可以做到读写分离.
数据库拆分 Sharding
纵向拆分 Vertical Sharding
将一个表拆分成为多个表, 每个表都有一部分字段. 就是分拆字段. 这里举一个例子:
比如 User Table 中会有如下信息: email, username, password, nickname (昵称), avatar (头像). 我们知道 email, username, password 不会经常变动, 而 nickname, avatar 相对来说变动较高. 可以将他们拆分成两个表: User Table 和 UserProfile Table. UserProfile Table 中用一个 user_id 的 foreign key 指向 User. 这样如果 UserProfile Table 挂了, 用户还是能够登录.
纵向拆分有很明显的缺点: 有些表不能进行纵向拆分.
横向拆分 Horizontal Sharding
一致性 Hash 算法
将 key 分配给一个较大的数, 比如 Redis Cluster. 然后各个节点平分这些数, 每个节点负责一个范围.
应该按照哪一个 Key 来做 Sharding
怎么取数据就怎么拆分数据
例子1 User Table
绝大多数的需求: select * from user_table where user_id=xxx
问如果我需要按照 username 找用户怎么办?
使用一张新的表单, 这个表单里面就两项, 一项是 username, 一项是 userid, 这样可以根据 username 来查询 userid, 然后再利用 userid 查询.
问在插入的时候怎么办, 现在没有 user_id?
- 手动创建一个 UUID 作为用户的 user_id
如果在刚开始设计的时候就已经使用了自增 ID 作为 user_id 怎么办
因为 UUID 是一个字符串, 与自增 ID 并不兼容. 可以单独开一个 Service 来维持全局唯一 ID, 加锁来保证操作线性化.
例子2 Friendship Table
双向好友关系是否还能只存储为一条数据呢?
当然不可以, 双向好友关系如果只存储为一条数据, 那么在查询的时候需要查询两个字段, 而 Sharding Key 只能有一个, 所以必然不可以.
单向好友关系
因为有两个字段 from_userid -> to_userid. 查用户关注哪些人就得查 from_userid 字段, 查用户的粉丝 (被哪些人关注) 就得查 to_userid.
因为这两个查询的需求都比较大, 而且比例基本一样, 所以我们就需要建立两种表, 一种表使用 from_userid 进行 Sharding, 一种表使用 to_userid 进行 Sharding. 这两种表的数据合并起来的话是一样的, 但是将他们分到各个机器上的子表就不一样了.
例子3 Session Table
Session Table 主要是按照 session_key 来进行查询. 所以如果要 Sharding Session Table 的话, 主要是按照 session_key 来进行 Sharding
标签:username,userid,数据库,扩展,user,拆分,Sharding,Table From: https://www.cnblogs.com/geraldkohn/p/17091086.html