目录

1. 功能需求

2. 实现方案

3. 数据库设计

3.1 预测数据量

3.2 按用户区间分表

3.3 定时任务数据归档

4. 缓存设计

4.1 怎么存

4.2 哪里存

4.3 缓存时间设置

1 功能需求

最近,公司 app 需要增加一个新的功能是历史浏览记录的页面。

说道 “浏览历史”,大家应该都不陌生,跟浏览器的浏览历史功能基本一致。浏览历史的功能,仅限于用户浏览文章页面, 记录用户浏览过的文章,一方面方便用户下次再次查找,另一方面,也对我们将来对用户画像设计有所帮助。

历史记录图片

2 实现方案

为了记录用户浏览过的文章,我们只需要在用户访问文章详情的页面进行记录即可。

可以采用“异步方式”,将用户浏览过的文章记录。

但是目前用户上百万,每个用户一天浏览量不很清楚,但是随时间递增,这个记录一定很大;所以我们采用新建一个 RDS 实例, 专门用来存放历史记录。

面对庞大的数据量我们应该如何进行分表呢?

3 数据库分表

分表前,我们先思考影响这个表的有哪些变量?

一般都离不开 “时间” 和 “用户数”。 所以我们到底是要采用按“时间分表”还是“用户分表”呢?

3.1 预测数据量

我们可以到服务器上看文章详情请求数。

1
cat 20200214.log | grep -E "articles/[0-9]+" | wc -l 

将一天文件中的文章详情数统计出来,也可以通过脚本获取一个月的文件进行统计。

然后我们可以根据我们的分表方式来对数据进行预测:

1) 通过时间-按月分表

这时候我们需要统计一个月的请求数,大致推测一个月数据 600w 左右的浏览量。

2) 通过用户-按用户id分表

这个时候统计的时候要考虑 user_id 的值,通过脚本给了个平均预测,一个用户一个月 50*30 = 1500。 (较大较理想情况,因为我们就是要防止一些大用户的操作)

根据数据和预测情况,我们可以简单看出其中的优缺点

1) 按月分表

优点:各个表数据量分布均匀

缺点

  1. 由于需求要展示最近三个月的数据,那么读取数据的时候比较麻烦,需要将多个月表的数据 union 后,进行排序和分页,union 后的数据不走索引,况且分页效率有点低。

  2. 如果用户突然增长,月表数据可能突破限制。这时候只能再通过月表再次分表。

2)按用户分表

优点:因为查询只针对个别用户可以充分利用索引,查询将十分简单高效,用户之间独立。

缺点

  1. 由于每个用户属性不一样,阅读数不等,造成数据量不平均。

  2. 用户数量级庞大,分表数量庞大

我们可以通过这两个优缺点进行取长补短,查询问题必须选用 “按用户分表”,那么如何解决用户表数量过多问题?

一般会有 按用户id取模分表,但是这种分表有缺点:

  1. 数量再次增大,想要再进行扩展分表比较困难;

  2. 取模运算如果是通过 mysql,取模将无法走索引;

3.2 按用户区间分表

所以我们可以选择 按用户区间分表,它呢补了上面取模的缺点,对后期单表中数据增大可以很方便继续再分; 例如我们 1w 个用户一张表,如果将来数据上亿,可以考虑变成 5k 个用户一张表,也就是在原来的基础上分成两张表, 通过脚本即可创建并迁移数据;

那么我们可以通过前面获得的访问量来确定大概要多少用户为一个区间;那么剩下一个问题了,当时间不短推移, 数据量还是很大,难道我们还要对再对用户分表吗?

1
2
3
$suffix = strval(floor($user_id / History::SPLIT_NUM)); $tablename = 'history'.$suffix; $this->setTable($tablename); 

3.3 定时任务数据归档

不,因为只展示用户最近三个月数据,所以我们可以通过定时任务对旧数据进行归档处理。 这样我们的表就一直控制在那个数据级;唯一可能上升的情况就是平均用户浏览数增多,不过影响不大,前面已经说了, 再次对用户进行划分也很简单。

注意,由于数据一直在这张表,所以主键就不要再用自增 id 了,因为日积月累的数据可能撑爆最大整型。可以用 UUID 或其他字符串类型等;


就此存储方案就好了,剩下显示方案;

关于显示,我们可以在表增加查询需要的所以,直接从中获取到我们的数据,速度很快;但是还有一个问题,就是 文章查询问题。

由于每篇文章可能根据运营人员更改而变动,所以一开始我们保存在浏览历史表中的数据将是关联id,例如此处是文章id;

这时候一种方法就是通过 join 文章表进行显示,但是这样三个月浏览记录去 JOIN 文章,可想而知这是一个噩梦;

那么我们还有另一个办法,通过缓存减少对文章的查询,也舍弃 join 文章的方法。

4 缓存设计

4.1 怎么存

如何设计缓存呢?和分表一样,我们也需要考虑几个变量。

这里我们要显示的是用户某一天查询的文章的分页,所以变量将是:

  • 用户id
  • 日期
  • 分页页码
  • 每页数量

如果用结果缓存,这个组合将非常巨大,并且 redis 存储不适合一次性存储超过 150kb 的数据;

所以我们可以通过 片段缓存 的方式来存储;

1)优点:多处地方都可以使用该片段缓存,缓存利用率高;

2)缺点:还是需要消耗一点点性能;

每个文章进行缓存,这样从性能上说,每次只是在浏览历史数据库将数据分页排序后取出,

对一页中的数据进行循环,每次循环直接内存中读取缓存即可。

最坏情况,循环每页数量去数据库搜索每篇文章(这个问题可以通过缓存存储触发位置来优化)。

4.2 哪里存

通过从产品上分析,用户是大多都是从文章列表点击文章详情进入,所以,我们可以在文章详情处就设置这个 片段缓存;当然,浏览历史的地方也要,只是浏览历史处命中率就变得非常高了,几乎已经先在文章详情处 进行了存储,所以循环取文章就变得非常少了;

4.3 缓存时间设置

TODO

浏览历史数据库表设计与缓存设计 - TsaiKoga Blog

327、浏览历史数据库表设计与缓存设计相关推荐

  1. CYQ.Data V5 分布式自动化缓存设计介绍(二)

    前言: 最近一段时间,开始了<IT连>创业,所以精力和写的文章多数是在分享创业的过程. 而关于本人三大框架CYQ.Data.Aries.Taurus.MVC的相关文章,基本都很少写了. 但 ...

  2. Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理

    基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客  QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...

  3. 点赞模块设计 - Redis缓存 + 定时写入数据库实现高性能点赞功能

    源码地址:github.com/cachecats/c- 点赞是作为整个系统的一个小模块,代码在 user-service 用户服务下. 本文基于 SpringCloud, 用户发起点赞.取消点赞后先 ...

  4. 【牛客 - NC93】设计LRU缓存结构(模拟)

    设计LRU缓存结构_牛客题霸_牛客网 描述 设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 k ,并有如下两个功能 1. set(key, value):将记录(key, va ...

  5. 精讲23种设计模式-基于装饰模式~设计多级缓存框架

    文章目录 一.装饰模式 1. 回顾多级缓存基本概念 2. 装饰模式基本的概念 3. 装饰模式应用场景 4. 装饰者模式定义 5. 基于Map手写Jvm内置缓存 二.手写一级与二级缓存 2.1. red ...

  6. 无码系列-6 数据缓存设计经验谈

    1.    缓存系统概述 1.1.  数据缓存的常识 u 为了解决什么问题 水平扩展:通常数据源站专注于数据存储, 对于负载能力.性能瓶颈不会做复杂的设计.缓存系统用于避免系统性能瓶颈,实现水平扩展. ...

  7. python文本框与数据库的关联_Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理...

    基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客 QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3. ...

  8. django自动生成问卷表的软件的设计与实现毕业设计源码291138

    摘 要 本论文主要论述了如何使用PHP语言开发一个自动生成问卷表的软件的设计与实现,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发.在引言中,作者将论述自 ...

  9. python 自动生成问卷表的软件的设计与实现 毕业设计源码291138

    摘 要 本论文主要论述了如何使用PHP语言开发一个自动生成问卷表的软件的设计与实现,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发.在引言中,作者将论述自 ...

  10. 聊聊微服务架构中的多级缓存设计

    大家好,我是不才陈某~ 今天我们来聊聊缓存这个话题,看看在微服务环境下如何设计有效的多级缓存架构.主要涉及三方面内容: Web 应用的客户端缓存: 应用层静态资源缓存: 服务层多级缓存. 首先,咱们先 ...

最新文章

  1. python信息管理系统统计功能_用Python实现职工信息管理系统
  2. Android SoundPool 的简单使用
  3. mysql简单的sql语句单表分组查询
  4. 数据库MySQL/mariadb知识点——数据类型
  5. 虚拟服务器设置 - 百度,百度云虚拟主机BCH配置伪静态图文教学
  6. python 多线程就这么简单(续)
  7. 63相似、合同、相抵
  8. 编写程序对给定的有向图(不一定连通)进行深度优先遍历_从零开始学习数据结构gt;图的非连通遍历...
  9. 社交电商源码-带直播电商功能-可DIY前端
  10. Windows系统下快速安装、配置Aira2,及图形界面配置、度盘、B站视频下载
  11. 利用CSS3制作网页动画
  12. 威漫哨兵机器人_曾经秒杀X战警的哨兵机器人,在漫威漫画原著里更让人头疼!...
  13. ThoughtWorks面试经历——武汉java开发
  14. Grafana的介绍与使用
  15. tensorrt遇到torch.bmm的解决
  16. 微信开发者工具中预览ApiCloud生成代码
  17. Qt QImage scaled方法缩放中的问题
  18. 云计算基础知识培训讲义
  19. target找不到*.xml和*.properties文件 报错:FileNotFoundException
  20. GeForce MX150相对应的NVIDIA CUDA版本_性能放心了:NVIDIA公版RTX 30系显卡设计频率可达2.2GHz...

热门文章

  1. Altium Designer--如何添加Mark点
  2. 新浪微博html不完整,新浪微博显示不正常怎么解决
  3. 高速列车横向17自由度模型
  4. [Google] 再见 SharedPreferences 拥抱 Jetpack DataStore
  5. vue echarts饼状图内部显示百分比
  6. hp台式计算机u盘启动设置,hp惠普品牌机设置u盘启动教程
  7. matlab如何运行程序
  8. flag--命令行参数定义多标签示例
  9. leetCode 318 最大单词长度乘积(位掩码,位运算,二进制)
  10. TOP100summit:【分享实录-猫眼电影】业务纵横捭阖背后的技术拆分与融合