参考文章
数据库分库分表(一)常见分布式主键ID生成策略
高并发网站如何解决数据库主键自增的时候出现重复?
其实大多数的都应该不会用到分库分表技术吧,我没有遇到过,也没有相关经验,只是做技术推演。
需求:随身学APP有题库,考试的功能。目前有2000个examine。但是,examine_log表有300多万的记录,大概1周有10万的增加,做一个技术预演。
1:app客户端要显示某一个考试的答题记录。管理员在一个考试时间截止之后,要导出用户的答题情况。明显的,分区键就是examine_id。在examine_log里面,有user_id,examine_id,question_id,option_id这4个关联主键。
什么是分区主键,所有相关examine_log的数据库操作语句都能加上examine_id!where examine_id=? 如果不能加上,那就比较麻烦了。
2:分表了,那examine_log的id怎么办?使用自增,我觉得也无妨,这个id不唯一也不影响我按照examine_id的维度做查询。 关于分库分表的id,保证唯一,顺序递增。我见到的开源项目都是uuid,这唯一,但是数据量大的时候,你对uuid建立索引,不是有序的,对索引影响太大。时间列可能是递增的,在时间列上面见索引比较好写。 就说Twitter的snowflake算法即可。
3:扩展怎么办?2个表变成3个表? 2个表变成4个表有数据库的平滑扩展方案,很帅气。你如果都重写做hash()取模,那就麻烦了。
这个examine_log这个分库分表是单维度的,没有什么问题,扩展也没有问题。
数据库秒级平滑扩容架构方案
需求:随身学app,目前有2000多篇的课程,2000多考试题库。其实根本就不用考虑分库和分表的问题。也是纯粹的技术预演。
1:train,examine里面都有一个role_name字段,每一个用户都是有角色的,都只能看到自己角色能看到的内容,select * from train where role_name regexp '^河南.* ' order by create_time desc;这个样。我想的就是按照 role_name 来进行垂直划分。可是,有管理员这个角色,他进去看到的是select * from train order by create_time desc; 没有where,你加不上这个分区键也不能加。无法按照分区主键来进行信息拉取。但是,毕竟集团用户是比较少的,后期各个省份地市进行统计也方便。
对集团用户不能按照分区主键拉取,使用二次查询即可。select * from train order by create_time limit 1000,10; 有3个省份,发送到3个表上面去select * from train_河南 order by create_time limit 333,10; 然后对比3个表的查询结果,找出最小的值,并记录各自的max.再次的查询:select * from train_河南 where create_time between time_min and max_河南。找到time_min在个个分库里面的位置,然后计算出他的全局位置。所有这些数据排序,得到全局视野。数据量比较小,但是,34个mysql查询,这转换的也?
那在线学习网站都是这样吗?他们的APP中,用户是没有角色的,每一个人看到的都是一样的。(可以认为是基本一样的,类似网易新闻,也可能不一样,今日头条个性化的推荐,手工进行个性推荐) 京东的商品目录,58的帖子服务,拉勾的招聘目录,这些都是一个目录一个一个分表吗?他们给出的答案,不是。
HR要查看自己发布的招聘需求,用户要查看自己需要的工作岗位。这个work_id是怎么分库分表的。order里面有 下单人user_id,有对应商户_id。我总可以讨好一方。你这个work,就是work_id,就是一个tiezi_id。用户的查看就是es的搜索,标签过滤。用户发布的也是es过滤,publish_id是user_id的用户。那你这根据tiezi_id好像谁也不讨好。你根据比如:java标签,讨好一个找java的程序员,你根据发布人publish_id,你可以快速定位发布人的表,少几次查询。你就根据tiezi_id或者work_id是谁也不讨好?谁也不讨好。统一存储,方便后期扩展。你现在java,c++将来别的吗?web,html 都新建吗?不能根据这个维度划分,越来越乱了。
一句话,暂时总结:数据库只提供tiezi_id的排序,其他都走elasticSearch,外置搜索完成。58的技术实现。
100亿数据1万属性数据架构设计
1:train如果按照时间排序,那么最近的100篇课程将会是可预见的热点。就使用train_id来进行分库分表了,那就二次查询方法。这不算两个维度!tiezi_id,work_Id,这种数据表只有一个维度的,就根据teizi_id,work_id来分库分表。业务多维度,别的方法解决,就是es解决。需求会是什么?发布人要看自己发布的帖子,100个表,100个sql,数据量小,很快聚合回来。用户要查看最新的帖子,招聘,二次查询搞定。也不会太慢,但是,如果你选择了一个业务维度来,也差不多,扩展起来也不方便,跨业务查询 其实根本原因是和按照主键差不多。但,扩展性就不行了。
train_id pulish_user_id xx xx 只有一个维度 根据train_id分区。
2:order按照order_id来分库分表了,你按照时间查询也没有问题,就是上面二次查询。但是,你查询用户的order,你又要查询商户的order,你这是另外的问题,二次查询也不行,涉及到业务了。那就是冗余!!凡是会有两个维度的,都使用数据冗余。
order_id pulish_user_id seller_id | commentid product_id user_id 根据业务id其一分
3:和JD的商品评论,58的帖子服务。他们数据量太大,冗余不起来,成本太高,都是使用elastic-search来进行分析的。业务优先的作为分区,评论就使用商品作为主键,通常用户习惯都是查看这里,较少有查看自己的评论记录的。