对计算机领域中间层的理解

以前看《代码大全2》时看到了如下一句经典台词:

“any problem in computer science can be sloved by another layer of indirecition”

“计算机科学领域的任何问题都可以通过增加一个中间层来解决”

当时只是觉得好就永远记住了,几年的编码经验,越来越感受到这句话的经典所在,下面来举几个例子说一下我对它的理解:



1.操作系统的缓存:

比较典型的用于阐述这句话的缓存实例,当属内存(包括swap、buffer、内存的cache)和cpu的Cache(有三个等级),

操作系统中数据总体读取流向:硬盘》内存》cpu。

swap:

当有应用需要读写磁盘数据时,由系统把相关数据从磁盘读取到内存,如果物理内存不够,则把内存中的部分数据导入到磁盘,从而把磁盘的部分空间当作虚拟内存(也就是swap)来使用。换句简单的话说,swap就是当内存不够时从硬盘中开辟的一块空间。

buffer:

当一个应用程序在内存中修改过数据后,因为写入磁盘速度相对较低,在有空闲内存的情况下,这些数据先存入内存的一块空闲空间(即buffer),在以后某个时间再写入磁盘,从而应用程序可以继续后面的操作,而不必等待这些数据写入磁盘的操作完成。简单说,buffer 是为了提高内存和硬盘(或其他I/O设备)之间的数据交换的速度而从内存中开辟的一块空间。

内存的cache: 从磁盘读取到内存的数据在被相关应用程序读取后,如果有剩余内存,则这部分数据会存入内存的一块空闲空间(内存的cache),以备第2次读取时,避免重新读取磁盘。

cpu的Cache:

Cache:高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。

又上可见,操作系统的缓存就是硬盘与内存之间,内存与硬盘之间的各种中间层,用于解决操作系统内部数据交互速度不一致的问题。

2.消息对列:

当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。“ 消息 ”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中,“ 消息队列 ”是在消息的传输过程中保存消息的容器

常用的业务场景如下:

1)业务系统触发短信发送申请,但短信发送模块速度跟不上,需要将来不及处理的消息暂存一下,缓冲压力。就可以把短信发送申请丢到消息队列,直接返回用户成功,短信发送模块再可以慢慢去消息队列中取消息进行处理。

2)调远程系统下订单成本较高,且因为网络等因素,不稳定,攒一批一起发送。

3)任务处理类的系统,先把用户发起的任务请求接收过来存到消息队列中,然后后端开启多个应用程序从队列中取任务进行处理。

4)在高并发环境下,由于来不及同步处理,请求往往会发生堵塞,比如说,大量的insert,update之类的请求同时到达MySQL,直接导致无数的行锁表锁,甚至最后请求会堆积过多,从而触发too many connections错误。通过使用消息队列,我们可以异步处理请求,从而缓解系统的压力。

消息对列就相当于两个应用之间的中间层,用于解决生产和消费的速度不一致的问题,能够提高系统的响应速度和系统的稳定性。

3.中间表:

具体应用比如闭包表、从属表等。

闭包表:用于分级存储的一个简单而优雅的解决方案,它记录了树种所有节点间的关系,而不仅仅只有那些直接的父子关系。

比如一个评论表,一般建表如下:

CREATE TABLE Comments (

comment_id bigint unsigned not null auto_increment  primary key,

parent_id bigint unsigned not null,

comment text not null,

foreign key (parent_id) references Comments(comment_id)

)

这样建设虽然简单,但是当一个评论下面有很多分支的时候,无论你是用程序还是用sql语句去处理这种层级关系 ,都是比较低效的。

一种很好的解决方案技术增加一个中间表,用于存储各个评论之间的关系(包括自己与自己,自己与子孙之间的关系),将刚才的表拆分为两张表如下 :

CREATE TABLE Comments (

comment_id bigint unsigned not null auto_increment  primary key,

comment text not null

);

CREATE TABLE TreePaths(

ancestor_id bigint unsigned not null,

descendant_id bigint unsigned not nul,

primary key(ancestor_id , descendant_id),

foreign key (ancestor_id) references Comments(comment_id),

foreign key (descendant_id ) references Comments(comment_id)

);

这样增加一个中间表后既使关系很清晰,在查询、做统计分析和增删改的时候也简单多了。

从属表:仅用一列来存储多值属性,将多个值存在一张单独表的多行中而不是一张表的多列中。

比如创建一个有多种属性值的表,一般建表如下

CREATE TABLE Bug(

bug_id int unsigned not null auto_increment  primary key,

description varchar(1000),

tag varchar(500)   //用json格式存储

)

或者

CREATE TABLE Bug(

bug_id int unsigned not null auto_increment  primary key,

description varchar(1000),

tag1 varchar(20),

tag2 varchar(20),

tag3 varchar(20),

tag4 varchar(20),

)

这样建设虽然可以,但不优雅,在做统计查询或者增加一种属性时就比较费力了,这是可以增加一张中间表(从属表)单独用来存储bug的属性,具体建设如下

CREATE TABLE Bug(

bug_id int unsigned not null auto_increment  primary key,

description varchar(1000)

)

CREATE TABLE Tag(

bug_id int unsigned not null,

tag varchar(20) not null,

primary key (bug_id,tag),

foreign key (bug_id) references Bug(bug_id)

)

这样修改后的表在做查询和统计的时候比较高效,在增加和删除的时候级联关系也很严格。

主键的约束能够保证不会有重复的记录出现,一个给定的标签只能和一个给定的Bug关联一次。

每个Bug也不在只限于几个标签,可以很方便的扩展成tagN 的列。

表建设过程中增加一个中间表非常适用于“有关系”的字段,既方便扩展也方便做普通查询和统计查询,严格的关系也可以通过外键加以控制,只是在查询的时候多了几个join(通过索引并不影响查询效率),这么好的想法,那就赶快在新项目中尝试吧。

以上只是通过操作系统的缓存、消息队列、中间表这三个实例阐述了我对“any problem in computer science can be sloved by another layer of indirecition”这句话的理解,这句话不仅适用于计算机领域,其他工程领域比如工程建造、机械建设、系统流程也是适用,所以经典之所以经典,是因为经典的东西不仅能帮你解决手中现有问题还能帮你解决以后可能出现的问题,还很富有哲学,能应用到各个领域。



写在最后的话:

“书中自有黄金屋 书中自有颜如玉”,也许你现在读的不一定现在就懂,等你经历的多了或者读得多了再回头看看,也许你会微微一笑,虽不至于倾城倾国,倾自己倒是绝对可以的。骚年们,当你走的路不多时,那就多读书吧。



参考博客:

http://blog.csdn.net/bingqingsuimeng/article/details/51858858

http://www.cnblogs.com/xuyatao/p/6864109.html

http://www.ywnds.com/?p=5791

参考书籍:

《代码大全2》、《SQL反模式》

时间: 2024-08-29 05:12:59

对计算机领域中间层的理解的相关文章

信息领域的本体理解

一.本体发源 本体发源于西方哲学,从西方哲学史来看,本体论作为一门学问起源对万物本原的追问.本体论关注的是"存在",即世界在本质上有什么样的东西存在,或者世界存在哪些类别的实体. 本体论在计算机科学领域的发展也与人工智能和信息技术的起步和发展密不可分的. 但在信息领域,既要借鉴哲学本体论思想的内涵,又要考虑本体论在人工智能和信息系统领域应用的具体特点对本体做进一步.规范的定义. 二.本体的定义 斯坦福大学的Gruber T. R.于1993 年给出了计算机领域本体的定义,即"

[CSDN] OpenCL用于计算机领域的13个经典案例

http://www.csdn.net/article/2013-10-29/2817319-the-application-areas-opencl-can-be-used 摘要:当使用加速器和OpenCL时,哪种类型的算法更加快速?来自弗吉尼亚理工大学的Wu Feng教授和他的团队例举了一份算法列表,分享了OpenCL常被用于计算机领域的13个经典案例. 哪种算法可以最好的映射GPU及矢量处理器呢?换句话说,当使用加速器和OpenCL时,哪种类型的算法更加快速? 来自弗吉尼亚理工大学的Wu

计算机领域国际会议分类及排名

http://blog.csdn.net/pipisorry/article/details/46302623 Computer Science Conference Rankings AREA: Databases Rank1: SIGMOD: ACM SIGMOD Conf on Management ofData PODS: ACM SIGMOD Conf on Principles of DBSystems VLDB: Very Large Data Bases ICDE: Intl C

欢迎自己加入到计算机领域!

搭上90年代末班车的我,在初中时,就对编程有着浓厚的兴趣, 自己却没有分清游戏与学习的轻重,因此耽误了学业. 阴差阳错地进入了工业领域——机械设计制造类, 尽管不是心怡的专业,我也是以常年名列前茅的成绩完成了学业, 但对专业没有兴趣的我,在实习时发现自己没有什么上进心, 最后决定向心爱的计算机领域进军. 任何文字都无法将才疏学浅的我塑造得满腹经纶. 只有努力学习,才能把我武装起来,我的新起点——2020年,冲呀! 原文地址:https://www.cnblogs.com/FuroOuO/p/12

计算机内存模型 粗浅理解

对于计算机内存模型,我认为可按 数组 模型进行类比.将计算机的内存结构等同于 数组 存储结构(其实这里反过来才是正确的,数组存储的模型是依照计算机的内存模型进行存储的,但这里为了更容易理解,就将其反过来思考). 一般而言,对于不同的机器,其内存高低字节存储位置可能不同,这就是所谓的大端小端.这也给我们的理解带来困惑. 而在我的机器上,我测试出来的结果是:以竖直内存模型分析,低地址在上,高地址在下方. 验证程序: #include "stdafx.h" #include <iost

02,计算机组成与操作系统的理解、对程序的理解、OS发展史 以及 一些杂项

这里马哥讲了好多,能听懂,但需要记得东西好少,不过我还是 按照 我 对 计算机 的 理解 画了 一张 图, 不一定 准确 , 但是 差不多 把, 计算机 底层 是 由 运算器.控制器.存储器.输入设备.输出设备 这 五大部件 组成 的 其中 运算器 和 控制器 是 在 cpu 中 的, 运算器 是 负责 计算 的, 控制器 是 负责 控制 程序 流程 的,也 负责 控制 存储器 中 的 数据, 北桥 是 一个 高速 I/O 设备, 他 通常 用来 连接 内存,硬盘,显卡 等 需要 高速 I/O

那些让你对计算机有更深理解的基础知识

本文着重介绍计算机基础知识,知道这些知识后,会让你对计算机有更深的理解. 信息的表示和处理 计算机如何表示整数:有符号数和无符号数,尤其是如何用补码表示负数,数字的取值范围. 计算机如何表示浮点数,为什么小数的二进制表示法只能近似表示十进制小数. 数值的转换.移位 这几点非常重要,因为几乎所有的编程语言都有数据类型,而最基本数据类型必然包括整数和浮点数. 搞不清这些表示和运算,在编程中就会遇到一些稀奇古怪的问题. 从汇编层面理解程序的执行 顺序.分支.循环.函数调用.数组.结构体等在汇编层面是怎

浅谈计算机领域及职业憧憬

虽然自己的专业是计算机,可是惭愧的说其实对这个行业的了解并不是很多,大多时候是通过网络或者新闻才了解到的.据我所知,现在计算机行业是非常流行的行业,当然竞争也是十分激烈,信息化的时代我们的生活都离不开与计算机有关的东西,比如上学坐公共汽车,需要刷卡,这就是信息处理:用手机上网,这就是数据库--我们不难发现计算机与我们的生活密切相关,我当时选择计算机科学与技术这一专业的时候,就是抱着对计算机的热爱,从小学就开始接触计算机,也会简单使用了一些软件的功能,像Microsoft Office.Photo

计算机领域中的豆知识

豆知识,出自日语まめちしき.表示一些边边角角的,一般不引人注意的小知识.类似于中文中的冷知识. 为什么(Linux下)C语言编译后的可执行文件的默认名称是a.out? 在Linux中,使用gcc编译C源码,在不使用-o选项指定名称的情况下,默认生成的可执行文件的名称是a.out. 很多人可能认为a是字母表的第一个字母,代表英文字母表中的a,或希腊字母表中的α.其实所谓的a.out的含义是assembler output,即汇编器输出. 了解编译过程的我们应该大都知道,汇编器的输出是目标文件(.o