高并发服务器的设计-缓存的设计

上传人:枫** 文档编号:511292425 上传时间:2023-09-27 格式:DOC 页数:4 大小:163.50KB
返回 下载 相关 举报
高并发服务器的设计-缓存的设计_第1页
第1页 / 共4页
高并发服务器的设计-缓存的设计_第2页
第2页 / 共4页
高并发服务器的设计-缓存的设计_第3页
第3页 / 共4页
高并发服务器的设计-缓存的设计_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《高并发服务器的设计-缓存的设计》由会员分享,可在线阅读,更多相关《高并发服务器的设计-缓存的设计(4页珍藏版)》请在金锄头文库上搜索。

1、高并发服务器的设计-缓存的设计为什么需要缓存呢?很简单的道理,拿QQ做个比方,每天有几亿用户登录、查询个人信息,且这些信息基本不会变化,如果你是架构师,你会选择全部从数据库中查询么,估计会被笑的。一些业务要求大量且高速查询的,数据库必然会成为瓶颈,虽然可以通过横向扩容的方式优化,但这不是最优方案,其实服务器优化没有一个放之四海而皆准的最优方案,业务不同,最优方案也不同。举个例子,腾讯有十几亿用户,就光登录就是个头疼的事,做架构的往往要朝最坏的地方想,比如所有用户同时登录怎么办,难道要像12306那样直接不理你呢?这样的业务其实并不复杂,却只有一个追求:高速响应,因为用户是用脚投票的。这些信息都

2、是存放在数据库中的,最终都要和数据库交互,我们用图来显示一次登录的周期:如果一个用户频繁的登录,注销,服务器是不是总要重复这个周期呢,当然不用,第二,三步取了的数据完全可以放在内存中,周期变成这样:可以看到当第5步再次请求后,系统已经没有了查询数据库的过程。这时候缓存就粉末登场了,就是适当的时候要用些内存来代替硬盘,很简单,内存和硬盘的速度不在一个层次上,只要花些money就可以了。如何设计缓存呢?缓存是占内存的,但不是以花尽内存为追求,尼玛,要是哪个架构这么想的,那就是太坑老板了。相反缓存追求的就是尽量少占内存,这和开头说要占内存不矛盾,因为终极追求是高效,把红管子换成土黄色(请看 “内存池

3、的设计” )。每一个缓存的方案其实都是一个平衡:快速索引与内存空间,既使你毫不在乎内存的占用,这个平衡还是存在。缓存方案又分为索引方案、存储方案、排序方案,三者往往是分不开的,在一类业务数据里找出唯一的KEY其实很容易,难的是如何建立索引,如果用标准库自带的map,红黑树方案,这只是解决了存储方案,如果KEY是20个字节,咱顺便也打算用std:string自带的比较函数,好吧,我承认咱找到了一个通用的方案,且这么认为吧。还是拿QQ为例,QQ号是9位数的数字,如果把这个数字定义成一个int型的,做为数组的基标,把数据全放进这样的数组中,理论上完全可以,那么要多大的内存去存储呢,假设每个用户128

4、字节的信息量,那么就要27*232=512G,好吧,咱实实在在的坑了回老板。现实中,不是所有的数据都要放在缓存中,比如有些QQ一年都不登录一下,还有放进缓存的必要么。对于大量的数据,在需要考虑内存的时候,缓存中应该只存放频繁用到的数据,像女人一样,要保持常鲜才是最美的。频繁度就是一个阈值,实际就是我们的经验值。再举一个实际碰到的例子,key是32个字节的,如果用字符串的比较函数,性能上比较憋屈。可以将32字节换成8个int型或者4个long long型,因为CPU可以直接对两个整型进行比较。实际开发中,我将32字节的key分成了8个int,将所有的缓存数据按模分类分级,先定义中间容器的结构:t

5、ypedefstructyumei_cache_container_syumei_cache_container_t;structyumei_cache_container_sintcontainer_num;intdata_num;yumei_cache_container_t*container;void*data;intmm0;容器中套有容器,是为了分级散列,对数据的分级散列是很个很不错的方法,可以提高精度,节省时间。再定义索引数据的结构:typedefstructyumei_cache_map_data_syumei_cache_map_data_t;structyumei_cache

6、_map_data_sintkey8;inttimes;intstart_time;void*data;yumei_cache_map_data_t*next;times是指这个数据被查询过多少次,start_time 则是开始查询时间,这两个参数是为了新陈代谢用的,比如一个数据在昨天天被查了30次,times=30,在昨天会被当成频繁数据加到缓存里,但是今天一次都没有查过,这样的数据就要被淘汰出去。定义完了数据结构,就剩下算法了,主要推荐两种:1.红黑树2.hash mapC里用的红黑树比较多,另一些语言比如JAVA,Phthon用的 hash map较多,两者各有优点。红黑树的查询速度不见

7、得会比 hash的快,但是会很稳定,后面文章我再讲一下吧。架构设计讲求透明性,上面定义的这些结构是对外不可见的,对外的文件接口应该是这样:intyumei_cache_module_init();intyumei_cache_module_release();intyumei_cache_insert(int*key,void*data);intyumei_cache_get(int*key,void*data);intyumei_cache_del(int*key);在模块内部定义一个全局变量就可以了。如果追求通用性,则需要重新定义接口:typedefstructyumei_cache_sy

8、umei_cache_t;structyumei_cache_svoid*container;#defineYUMEI_CACHE_ERROR-1#defineYUMEI_CACHE_OK0#defineYUMEI_CACHE_KEY_EXIST1#defineYUMEI_CACHE_KEY_NOT_EXIST2yumei_cache_t*yumei_cache_create();intyumei_cache_close(yumei_cache_t*cache);intyumei_cache_insert(yumei_cache_t*cache,int*key,void*data);intyu

9、mei_cache_get(yumei_cache_t*cache,int*key,void*data);intyumei_cache_del(yumei_cache_t*cache,int*key);有了这些只是提供了正常缓存的功能,别忘了我们还要追求内存少浪费,就要保持数据的常鲜,还得定时去代谢那些老数据,这样就得要做到四点:1.数据库存放的数据都是有状态的。2.从数据库中查询的数据需要有最近的访问时间和访问次数。3.缓存中的数据要和数据库中打通。4.提供定时代谢的规则。相应的缓存过程是这样的:当用户查询数据,首先在缓存中寻找,缓存中不存在,则去数据库中查找,并更新数据库的访问时间和访问次

10、数,当访问次数达到缓存要求则将其放进缓存中。系统定时对缓存清除一些满足代谢规则的数据,这个规则是访问时间、访问次数、系统容量的一个权衡。上面的接口就要改成这个形式:intyumei_cache_insert(int*key,void*data,inttimes,intstart_time);intyumei_cache_check();或者:intyumei_cache_insert(yumei_cache_t*cache,int*key,void*data,inttimes,intstart_time);intyumei_cache_check(yumei_cache_t*cache);ty

11、pedef struct yumei_cache_s yumei_cache_t;struct yumei_cache_svoid* container;#define YUMEI_CACHE_ERROR -1#define YUMEI_CACHE_OK 0#define YUMEI_CACHE_KEY_EXIST 1#define YUMEI_CACHE_KEY_NOT_EXIST 2yumei_cache_t* yumei_cache_create();int yumei_cache_close( yumei_cache_t* cache);int yumei_cache_insert( yumei_cache_t* cache, int* key, void* data );int yumei_cache_get( yumei_cache_t* cache, int* key, void* data );int yumei_cache_del( yumei_cache_t* cache, int* key );

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 机械/制造/汽车 > 汽车技术

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号