用户參与记录存储的演变

有这样一个应用场景:用户有两个连续的操作A和操作B,必须是操作A完毕后才干运行操作B,假设操作A没有完毕就触发了操作B,则显示用户须要先运行操作A,即在操作B运行须要查询操作A是否运行过。这里引申出来的问题是,记录用户參与记录,提供针对用户和操作的查询方法。当不同的数据量时,我们的存储方案会大不同样,随着数据的增长,方案不断演变。

1、数据量较小,用户操作行为固定:
存储:MySQL
方案:我们以UID为key,一行一个用户,每一个用户包含的用户作为列存储,比方UID=100,固定存储为操作A和操作B,则表结构大致例如以下:
table_operation
uid operation_a operation_b
100 1 1

假设我们要查询用户是否參与A或B时,直接使用SQL: SELECT * FROM table_operation WHERE uid=100 AND action_a=1就能够达成目标。

问题:用户操作固定,扩展较难,假设须要添加用户操作行为,则须要添加字段或添加表存储,添加字段的方法在一定的数据量级下面(比方100万)是可行的,假设行为间无关,则添加表存储方案的表现会非常不错。

2、数据量较小、用户操作行为不固定:
与场景1相比,当前场景除了uid这个变量,添加了用户操作变量,即我们须要关注用户和用户操作两个变量。
存储:MySQL
方案1:添加操作表,生成操作id,用户操作行为表存储uid和oid。当用户运行一个新的操作时就在操作行为表插入一条记录。其表结构大致例如以下:

table_operation_info
oid name
1 operation_a
2 operation_b

table_operation
uid oid
1 1
1 2

当须要查询用户1是否运行过操作A时,使用SQL:SELECT * FROM table_operation WHERE oid=1 AND oid=1。
问题:当用户的操作行为较多时,用户操作行为增长速度非常快,数据量也为逐渐增大,可能MySQL单表无法负载。解决方式在兴许场景中说明。

3、数据量较大,用户行为固定
存储:MySQL
方案:与场景1相比,当前场景不同在于数据量比场景1大,数据量大到MySQL单表负载只是来。此方案解决的就是这个问题,当单表太大时,性价比較高的方法通常是採用分表。我们当前场景的变量是uid,仅仅要根据uid按水平分表就可以。

4、数据量较大,用户行为不固定
存储: MySQL
方案1:此方案应用于用户的操作行为能够分类的情况,即在场景1的基础上添加两次分表操作,按操作行为类分表和按用户分表。当前方案中我们须要应对两个变量:操作行为和用户。两次分表分别相应这两个变量,按业务规则做操作行为的分表操作,按用户id水平切分降低数据量。

方案2:此方案是全然的水平分表操作,在场景2的方案基础上,按用户水平切分。

5、数据量超大
存储: MySQL
方案1:分库分表,此时一个库已经无法满足需求,规则根据前面的场景实现,根据实际的需求能够考虑把不同的库放不同的机器上。
方案2:在分库分表的基础上,按位存储,由于一个操作行为有没有运行过是一个是否的状态,即0,1状态,因此我们能够用一个位来存储,64位能够存储64个操作行为的标记。

其他存储
key-value数据库
我们的需求实际上并不须要太多的关系型数据库的功能,简单的 k-v数据库就能够实现我们的功能,而且在性能上也会有所提升,毕竟做得少,会快。
先无论是选择基于内存的,还是非内存的(能够依据实际需求来选择,也能够是热点数据在内存,沉默数据在非内存中),如果我们有足够的空间存储。
方案1:
以uid+oid为key,值能够存储状态,也能够仅仅存储是否參与(0和1),可是会存在key太多的情况,特别是当数据量超大时,uid的个数*oid的个数,可能是你无法相像的量级。
方案2:
一般来说,用户操作行为的数据量全然小于用户的量级,而且用户操作行为的数据可控。假设要降低key的个数,我们能够使用oid+用户分区索引id作为key,这里所谓的用户分区索引是指将用户以某个数量分成一个区,全部的用户都记录在这个这个区间内,比方以10000为一个区间,则uid为1到9999的用户分到区间0,这里能够以1和0存储用户是否运行了此操作,一个key相应的value初始化存储10000个0。当uid=100的用户运行了某操作,则将第100个0置为1。
方案3:
在方案2的基础上,将10000个0转换为10000个01位,如果一个位存储50位,则总共仅仅须要200个。
方案4:
当用户量超大时,大多数的用户对于某个操作可能都是没有參与的,则在方案3的基础上我们添加简单的稀疏矩阵压缩,给每一个存储位加入索引,当存储值不为0时才会存储。
方案5:
我还没想到,期待你的分享

小结

•随着数据量的增大,总的思路是分冶,当一个表搞不定时分表,当一个库搞不定时分库,当一台机器搞不定时加机器。
•对于不同的存储介质选择须要考虑成本和需求,全部的选择都是平衡后的结果。
•节省空间,按位存储。
•不要过早优化。

posted @ 2015-01-29 21:38  phlsheji  阅读(240)  评论(0编辑  收藏  举报