layout: post
title: 2016-04-25-信息系统实践手记5-CACHE设计一例
key: 20160425
tags: 业务 场景 CACHE 系统分析 系统设计 缓存
modify_date: 2016-04-25
---html
信息系统实践手记5-CACHE设计一例
说明:git
正文:程序员
- 信息系统实践手记系列是系笔者在平时研发中前后遇到的大小的问题,其中比较典型的内容加以收集和分享。
- 信息系统实践手记目录:博客园(或查看源码的README.MD文件)
摘要:github
正文web
1.CACHE是啥?
最近一直在了解scala,Spark,Python,数据挖掘,以及复杂科学的一些内容,在充实和忙碌之余,虽兴趣浓厚,但体力不支,疲劳的很,无奈耽搁了实践手记。
本来计划2周挂出一篇来分享,实在抱歉。要分享的东西太多,码字太费时间,有时候甚至以为开会也许更好(不少人反感开会,那是由于没开太高效的会)!其实不少东西主要仍是考本身去走,去体会。
闲话不说,切入正题。
不少研发人员,尤为是开发程序的同志,找到一个cache框架或类库可用,好比hibernate的cache功能,而后就一股脑用上去。虽然会有效果,很愉悦,是好事,既增长经验,也体会了框架的魅力和效率,
但其实还有东西能够进一步去领会。究竟为啥要用CACHE?CACHE是啥?什么样的场景用什么样的CACHE?不多有人问。
那CACHE究竟是啥呢?还真难于表述清晰,但有一些要点:
- CACHE的产生是为了缓解处理链上不一样节点之间速度不协调的状况。举例若干:
- 计算机系统:通常有速度梯度:CPU内部寄存器(register)IO>内存IO>磁盘IO>网络IO,为协调它们之间传递数据的速度差,就可设置缓存结构,叫CACHE;
- 说明1:以上说的是通常状况,不考虑特别的磁阵RAID,高速SCSI,千兆或万兆网络等;
- 说明2:CPU内部也分L1,L2,L3等多级寄存器结构,当作多级CACHE使用,早先的386/486处理器没分那么多层次;
- 地铁系统:有时候出事故,人特多,站内站外由管理员把守入口分批放人到1层大厅,则1层大厅是一个CACHE;管理员分批从大厅放人到B1层站台,则B1站台也是一个CACHE;当CACHE快撑满的时候,管理员就会喊“慢慢来,不要挤,暂时关闭,你们耐心等待!”,因而人就被囤积在不一样的CACHE里,以便协调地铁运量和人流涌入的速度差问题。
- 工厂流水线:另外一个典型例子是工厂的流水线。之前老式流水线每一个工位站1我的,处理1个装配动做,好比给黄小鸭玩具装上1条腿。一个工件,若是流经10个处理节点,那就会有10我的来处理10个步骤。显然,老板指望流水线一直处于充满状态,则最高效的源源不断有产出。但意外总会发生,好比某工件N流转到Px节点,Px节点的工人很累,处理较慢,致使Px-1步骤流出的工件不断堆积,而这个Px处理节点处理台的工件堆积场所,就是一个BUFFER缓存区(也就是CACHE),它愈来愈满,就提醒Px的工人,加紧干,不然一旦CACHE撑爆,就没法克服(追上)速度差(时间差)的问题!(画外音:能够看出流水线机制的高效和科学,以及“残酷”)。
- 生产者消费者模式:经典的程序设计模式“生产者和消费者”模型也有一个CACHE的设计,就是协调生产和消费的速度差,相似“工厂流水线”
- CACHE其实是用空间上的代价来缓解时间上的不协调。
- 你确定要问“既然速度有差别,那CACHE再大也没用?”,的确,再大的CACHE也是用来临时克服速度差别的,它指望能够用空间暂时的堆积追回偶发致使的时间不协调(速度差是绝对的,这个在设计场景以前就知道,但速度不协调是偶发的,这个要区别开!)。若是永远没法“追回来”,那么再大的CACHE也会有问题,那么就是设计上的问题,就不是CACHE机制能够解决的。
- 处理节点Px每每速度不一样,因此必须用不一样算法来安排。好比:
- 经过编译器编译的源码,会根据OS的不一样及其内存页面调度算法,互相结合,处理好代码的摆放,并充分考虑到CPU/MEM/DISK/NETWORK的差别;保持MEM代码段高命中,下降页丢失中断,等等。
- 程序自己也应该充分利用诸如“多线程”,“并发计算”,“分布式计算”等方法,来从宏观的算法层面,解决掉速度差别,从而适当的利用CACHE来防止偶发的速度不协调,而不是算法自己有永久性的硬伤“速度不匹配”。能够适当的使用一些主流成熟前三名的框架来解决实际问题。
- 程序终究是要达成业务须要的,也就是完成功能目标(Feature)。而功能和业务自己是有特色的,有时空特性的,是高并发业务?仍是随机业务?业务的时空特性如何?是否和上下班高峰有关? 是否和网站的维护周期有关?是否和购物的时间段有关?总之从业务触发,须要专业的领域知识(行业支持),而且须要深厚的技术功底,这样的从场景出发的系统分析和系统设计行为,是何其重要!这方面的人才很是紧缺。
- CACHE所处理的时空不协调,多是偶发的,也多是来自于业务模型;
- 经过上述的不一样层次(编译器,OS,程序,框架类库,业务场景分析)的讨论,基本上能妥善的处理业务,达成场景,使用必要的CACHE结构。但业务模型老是会偶发时空不一致,尤为是在当今多任务的计算机架构(之前主机时代只有大型机是多进程的,如今微机也是多任务并细化到线程)。很容易计算力不够须要增长更多CPU的core,数据量大没地方放,就增长MEM,MEM增长后也会致使低速的磁盘IO和网络IO也变大。
- 另外在对业务模型不断调优和扩容的过程当中,不协调也会天然产生的,而若是程序模型比较优秀,相关必要的地方原本就有CACHE,那么CACHE将为程序运做提供余地。
- 即使是简单的业务模型,并且调优完成,且一直正常运做。但也可能由于“网络故障,CPU失效,内存或磁盘损坏,某个计算节点离线”等问题而打破平衡。这时候,甚至连写LOG日志来记录状态也显得很奢侈或捉襟见肘。此时,若是程序在框架设计上已经未雨绸缪的安排了充分和必要的CACHE,则彻底能够提高健壮性,甚至在偶发灾难冲击中坚强运行,恢复运做。
- 客观世界和程序世界都是复杂的,而复杂系统常常引起意外和不协调,CACHE则应运而生:
- CPU里面的微指令集中用到了L1,L2,L3,它们就是各级CACHE;
- MEM,DISK,网卡等设备,不管在硬件的接口驱动程序BIOS中,仍是在程序员编制的应用程序中,都安排了CACHE,来处理设备受到外界速度不匹配的冲击。
- 程序设计中不少模式,好比消费者生产者,就必然有CACHE存在,以缓解生产和消费的速度不匹配;
- 真实世界的仓库存货,小超市囤货,高架路上的紧急停车带,上下岔道区域,展览会门口的回形排队护栏,流水线的每一个节点的BUFFER缓冲带等等,都是CACHE的好例子;
只有理解了天然现象,业务规律和程序能力边界,才能深刻体会如何在程序设计中,在什么样的业务场景下使用怎样的CACHE设计,以便到达好处和结果。不建议只为了技术用技术,必须明确使用的目的为什么,才能正确的使用。算法
2.CACHE设计一例
这里简单举一个例子,仍是前几篇分享的客户端和服务器,它们是提供GIS地图服务的服务器和客户端;而这个提供GIS业务的服务器就用到不少CACHE; 撇开客户端业务展示不说,不少后台服务是由作GIS业务的应用SERVER提供,简称为GS,而GS须要从设备管理平台,简称DS获取设备信息;设计模式
- 由于DS不提供设备信息的订阅(很遗憾),则没法使用高效的观察者模式来获取设备变动信息,而只能由GS经过阶段同步(轮询模型)来花巨大的代价向DS获取其实不多变化的设备更新信息。为了阶段同步,GS只能在内存(或DB)作了一个CACHE,来存放好比每30分钟的同步信息;
- 最早是X分钟同步,按照经典作法,同步数据放在DB。但为提高速度,解决业务场景的高速要求和DB处理的慢速状况,将DB的数据“上提”到内存的CACHE中,之后作业务直接查CACHE,处理CACHE;这里就天然的引起了一个问题,CACHE的脏数据须要同步回到DB,由于数据存在于两个地方,一个CACHE是临时的,一个DB是持久化的,那么它们之间也有同步问题,这是使用CACHE常常要面临的状况。其实最后由于原来程序框架作的不佳,致使了批量修改完成后,还遗留了很多小尾巴,只能case by case的修复,不细说。
- 咱们GS平台,还和第三方,好比一个城市的路口卡口管理平台(简称KS)对接,上次讲过平台对接问题了,这里假设顺利对接。那么KS的数据,也会阶段性的同步到咱们GS来。一个典型的应用是GS向KS订阅了一种“告警A”,当KS发生事件A而发出“告警A”时,将会推送到GS平台,那么GS平台分发给客户端。这里显然有速度的不协调,若是告警频繁,GS一时处理不过来,那么就要CACHE,怎么弄?也能够不用本身写代码,咱们GS和GS的客户端是经过ActiveMQ的消息中间件来传递消息。订阅以后,不一样主题的消息和用户就会有本身的BUFFER来存放,即使KS平台突发大量告警A到GS,GS来不及分发,那就放入MQ本身管理的缓存队列,MQ本身处理。固然这里咱们看到了上面讨论过的CACHE的几个问题:
- 若是KS平台的“告警A”一直高频持续发送,那么最终GS接收代码来不急放入MQ,或者来得及放入MQ,但MQ终将崩溃。因此这里就遇到了前几篇提到的平台对接中,对两个有交互的平台之间的信令和数据的“时空特性”必定要定义清晰,好比咱们GS和KS就定义了最高并发不能超过1秒10条(10CAPS),不然GS拒绝而不是经过CACHE尽可能容纳和处理。万事都有限度,讨论清楚就行!
- 这里还有一个隐蔽问题,你们不知道看出来没有。这里假设我GS的JAVA接收代码,从网络socket套接字获取的批量字节流,速度极快,放入MQ几乎不花时间。若是没有这个假设,并且放入速度的确很慢,那么MQ不会最终“爆炸”,首先奔溃的及时GS的接收代码片断。这个判断,通常是根据程序员的经验和业界的经验来肯定的。它老是很是快,放入message,通常老是比消费处理message快很多。
- CACHE也能存在于高层次和高抽象级别的。好比当前的hibernate库支持对象到DATA MODEL的映射,而业务是针对对象,不是直接赤裸的和数据交互的。针对对象的操做好比func1()也是能够CACHE缓存的,以便第二次一样的调用func1()的时候,极大的提高速度和效率。 这里固然也会看到一个脏数据和失效的问题,再也不讨论。
END