为什么超长列表数据的翻页技术实现复杂(二)
为什么80%的码农都做不了架构师?>>>
上文为什么超长列表数据的翻页技术实现复杂提到了超长列表翻页技术设计上一些问题,今天讨论下部分解决思路。
前新浪同事 @pi1ot 最近在程序员杂志发表的一篇文章《门户级UGC系统的技术进化路线》也是超长列表的一个经典案例,在正式展开思路之前,我们也不妨了解一下此文所说新浪评论系统的演进思路。
从文中看到几个版本的列表翻页实现方案
3.0版
3.0系统的缓存模块设计的比较巧妙,以显示页面为单位缓存数据,因为评论页面是依照提交时间降序排列,每新增一条新评论,所有帖子都需要向下移动一位,所以缓存格式设计为每两页数据一个文件,前后相邻的两个文件有一页的数据重复,最新的缓存文件通常情况下不满两页数据。
此方案由于每页的条数是定长的,因此主要采用缓存所有列表的方案。但为了数据更新的便利,缓存结构比较复杂。从今天多年之后的眼光来看,这种设计不利于理解、扩展及维护。因此目前大多不倾向使用这种方案。
4.0版
解决方案是在MySQL数据库和页面缓存模块之间,新建一个带索引的数据文件层,每条新闻的所有评论都单独保存在一个索引文件和一个数据文件中,期望通过把对数据库单一表文件的读写操作,分解为文件系统上互不干涉可并发执行的读写操作,来提高系统并发处理能力。在新的索引数据模块中,查询评论总数、追加评论、更新评论状态都是针对性优化过的高效率操作。从这时候起,MySQL数据库就降到了只提供归档备份和内部管理查询的角色,不再直接承载任何用户更新和查询请求了。
使用自定义索引的方式,由于未与相关人员交流细节,推断应该是类似数组的结构。
从上述案例看到,评论系统是一种典型的超长列表数据结构,如果再MySQL的基础上来做,需要设计额外的索引结构来实现高效的翻页功能。
由于超长列表的翻页实现成本高主要是由于列表索引的B-TREE结构方面原因,B-TREE结构能快速查找到某个key,但不是为叶子节点的Range访问而设计,因此主要解决思路也是围绕B-TREE的range访问而进行优化。
首先、从原理来看,可以在B-TREE增加以下2个二级索引字段:
- Count index 记录每个非叶子节点下的条目数,这样可以帮助快速定位到任意的offset;
- Offset index 记录部分叶子节点的offset,比如每隔1000个id记录一个offset如下,并保存在另外一个列表中,当需要查找某个offset的时候,则可以利用附近已经记录offset的id来定位目的地位置。比如当翻页到1010时,如果offset index记录了[1000: id10345],则可以从id10345往后10个元素找到10010。
[
{"1000":10345},
{"2000":13456},
{"3000":22345},
{"4000":56789},
{"5000":66788}
]
这2个字段可以同时使用,也可以只用其中一个。如图
再看如何将上述方法应用到具体的实现中。由于本文主要讨论MySQL环境,MySQL要在B-TREE上额外保存一些信息需要修改MySQL源代码,修改门槛较高,因此更简单方法是将上述二级索引通过应用层保存在另外的表中。
一种非严格意义的count index实现如下:
CREATE TABLE IF NOT EXISTS `second_index` (`id` int(11) NOT NULL AUTO_INCREMENT,`uid` int(11) NOT NULL,`yymm` int(11) NOT NULL,`index_count` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `second_index` (`id`, `uid`, `yymm`, `index_count`) VALUES
(1, 1, 1409, 123),
(2, 1, 1410, 2342),
(3, 1, 1411, 534),
(4, 1, 1412, 784),
(5, 1, 1501, 845);
一种offset index实现如下:
在第一次用户翻页到某个offset位置时,在redis直接保存offset, id。当有其他请求来查找offset之后数据时,可以从offset的位置往后扫描。如果列表的数据发生了变化,需要及时将Redis保存的offset index删除。
以上2种方法已经在生产环境使用。
转载于:https://my.oschina.net/boltwu/blog/424231
为什么超长列表数据的翻页技术实现复杂(二)相关推荐
- python爬虫,记录一下爬取过程,列表数据,翻页,post方式,保存字典
记录一下自己的爬虫的过程把,最近在做个项目. 要爬取的网站比较简单. 其中的问题是: post方式,网站的数据有一些需要使用post方式才能获得. 比如, 这部分要看到<发起的项目>,需要 ...
- 表格设置翻页 html,使用原生JS实现表格数据的翻页功能
使用原生JS实现如下图所示表格数据的翻页功能: HTML代码: 表格标题 < > 简单处理一下样式,CSS代码: #pagination { text-align: center; } # ...
- 导航电子地图数据中POI搜索技术原理之二
导航电子地图数据中POI搜索技术原理之二 支持任意检索 <浅谈导航数据中POI搜索技术原理>一文介绍了导航电子地图中POI兴趣点数据进行关键字检索的基本原理. 其中,数据的组织方式如下: ...
- 八爪鱼爬取列表数据和详情页数据(国内网址)
1.一般来说想爬取详情页的数据都会先把列表数据(带上详情页的链接)先爬爬出来再专门爬取详情页的数据. 2.爬取详列表数据步骤: 1.打开网页 2.循环翻页(注意:八爪鱼免费版一次只能爬取1w条数据,所 ...
- Python爬取数据:翻页操作
Python爬取视频在上一章已经实现,如果爬取数据的时候发现不止一页数据,而是很多页数据的时候,我们就需要爬虫自行翻页操作继续获取另一页的数据.那么如何实现的翻页操作是本章主要描述内容. 该文章爬取数 ...
- 前嗅教你大数据:采集带有翻页结构的网页数据
置顶 "前嗅大数据" 和数据大牛一起成长,做牛气哄哄的大数据人 [场景描述]采集带有翻页的网页中的数据. [使用工具]前嗅ForeSpider数据采集系统,免费下载: ForeSp ...
- ASRUL智能翻页扫描机器人
ASRUL智能翻页扫描机器人 2019年12月8日至9日,首届世界一流企业R&D与创新管理高端论坛在北京举行.本次论坛由教育部人文社会科学重点研究基地清华大学技术创新研究中心主办,北京联合大学 ...
- VMware 虚拟化编程(10) — VMware 数据块修改跟踪技术 CBT
目录 目录 前文列表 数据块修改跟踪技术 CBT 为虚拟机开启 CBT CBT 修改数据块偏移量获取函数 QueryChangedDiskAreas changeId 一个 QueryChangedD ...
- ASP NET Core --- HTTP 翻页、过滤、排序
参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/v07647j3zkq.html 翻页, 过滤, 排序等 – 如何传递参数? Query ...
最新文章
- C++ 笔记(07)— 常量(字面常量、const定义常量、constexpr 定义常量、enum 定义常量、define 定义常量)
- Django框架进阶
- 设置Linux下Mysql表名不区分大小写
- Uedit32和Ubuntu 选定跳转
- HashSet,TreeSet和LinkedHashSet的区别
- Python学习笔记(1):用户输入,终端输入
- 中如何刷新当前路由_企业装修和家庭改造中,路由器及接收器如何安放
- 以太网帧的最小长度_802.3?以太网?看完你就懂了
- 各类数据库问题描述模板
- 【算法】—— 最大子序列和问题
- unix系统发展史3
- 学习笔记-状态方程精确离散化
- RAID磁盘阵列管理
- 手机屏幕分辨率说明大全 VGA - hd
- # 个人日记-书籍《银河帝国2之基地与帝国》观后感-20210808
- RecyclerView 报Scrapped or attached views may not be recycled. as Scrap:false isAttached:true异常
- 副本全攻略之哀号洞穴(超详细)
- 电子计算机进行会计核算 其会计,1. 使用电子计算机进行会计核算,其软件与其生成会计 ….doc...
- 【mmdetection小目标检测教程】三、使用sahi库切分高分辨率图片,一键生成coco格式数据集
- 盘点几款还不错的企业网盘产品
热门文章
- OD-标志寄存器判断语句对照表(汇编标志位寄存器对照表)
- JAVA线程之生产者消费者问题
- 浅入深出Vue:子组件与数据传递
- Vue-easyui中如何给ComboGrid添加过滤器
- Java关于周跨年的周数计算
- linux audit审计(6)--audit永久生效的规则配置
- PRISM ‘VS100COMNTOOLS’ not set. Cannot set the build environment
- laravel CURD
- (转)Android属性设置android:noHistory=true
- 学习笔记之23-typedef