程序编程滥用内存的现象为何这么多

浏览:/ 2018-01-30

好吧,今天又双要提小密圈,不过这次真的不是为了拉粉,而是因为恰好这个场景,在技术设计上很典型。

 

小密圈春节后爆发很快,那么技术上就遇到了一些瓶颈和问题,吴总就拉了几个好朋友做技术顾问,帮他们参谋一下,有幸我就成了其中之一。

 

先处理了两个数据库慢查询的问题,证明了我对数据库的索引理解依然还能用的上,不过这不是什么关键问题,因为系统负载和瓶颈不在这里。

 

那么,在对方的配合下,我们就对程序负载做了抽样的分析,并将一些执行开销略大的脚本负载,通过性能分析工具做了一下拆解,然后注意到,绝大部分开销较大的请求,是用户进入特定圈子首页的脚本,而这里开销最大的部分,是内存的频繁请求。限于信息安全的考虑,对过于细节的技术描述,很抱歉,我不会展开,我只基于这个案例,展开说一下关于比较常见的设计思路误区,和一些设计的思考方法。

 

通过这个案例我意识到一个现象,其实很多小创业公司都可能遇到的现象,一些技术人员,对系统开销的理解不够彻底,不够扎实,会有一些简单的标签化思维,比如说,数据库往往是性能负载的瓶颈,而使用内存数据存储,可以避开数据库的瓶颈,从而实现性能和响应能力的提升。

 

这个想法,不能说是错的,因为我们遇到数据库瓶颈的时候,也是通过内存数据存储来优化的,但不能简单化这个问题。并不是说,所有场合,内存存储都比数据库更优越。

 

以前我举过一个我们自己的案例,我们存储用户session的时候,用了mysql 的heap类型数据表,这是内存表,这个表的存取频率是极高的,但因为写入过于频繁,结果,锁表严重,经常卡死,导致系统因数据库等待被整个卡掉,当然,这可以认为是一个经验不足的菜鸟问题,结果换为innodb,行级锁,问题就解决了。 那么,从内存表换成物理表,看上去是性能下降的,但因为行级锁比表级锁更可靠,在频繁写入的情况下,如果i/o撑得住(请注意这个前提哦),那么实际上可靠性是更优的。

 

那么回来说,关系型数据库,我们常用的数据库结构,其索引类型,差不多是btree相关的,具体呢,我也不是很精通,在索引优化到位的情况下呢,其查询效率呢,趋近于log2(N)。而一些内存表结构,哈希索引,其查询效率,通常趋近于1,也就是寻址搜索,这个针对你明确的key- value查询,绝对是有优势的,(当然,根据一些信息安全测试的披露,在特殊情况下,可能查询效率会直线下降,但这个不是今天要谈论的重点,就列在这里,以免有人挑错。)

 

但这里有两个延伸问题

 

问题1:哈希索引只适用于key - value这样的简单查询,而关系型数据库可以适合较多的条件查询。 也就是哈希索引实际上适用空间是极为有限的。而且也不支持排序等操作。

 

问题2:并不是所有内存数据表结构都是哈希索引,比如前面提到的mysql 的heap表结构,其实也是关系型数据库,btree类型的索引。那么另一个特别要提到的,是redis有个常见结构,有序集合,因为这个结构支持排序,支持快速的排名统计,所以应用范畴也很广,但是要特别说明,这个表结构,存取的开销是远大于哈希结构的。

 

有序集合有一个极佳的替代关系型数据库的应用场景,就是积分排名的场景,以前技术大牛云风提到过一个经典案例,某友商的游戏,积分排名挂死数据库,这是很常见的一个问题。

 

一般使用数据库做积分排名,随便写一个,懂SQL的都能看懂。 select count(*) from gamepoints where points>$mypoints  。得到的统计数据+1,就是我的排名。但这个SQL的开销怎么计算,这是一个很经典的数据库负载测试题,在你使用points作为索引的前提下,其负载开销与你的排名线型相关,也就是,你要是排名靠前,负载几乎可以忽略,你要是排名靠后,负载直线上升。无论任何数据引擎,无论myisam,还是innodb,无论mysql还是sql server。如果不动技术架构,不改产品设计,纯SQL优化,两个字,没戏。 

 

这个场景,使用redis 的zrank来处理,爽爽的解决,毫无压力。这是这个结构最有价值的地方。但一切都是有条件的,其插入,更新,删改的系统开销,要远高于redis的其他数据结构。 而其价值,仅仅在这个场合,是具有绝对优势的。

阅读"程序编程滥用内存的现象为何这么多"的人还阅读

上一篇:原创文章不收录的SEO原因有哪些

下一篇:人工智能如何让SEM营销落地