Memcache应用场景介绍
面临的问题
对于高并发高訪问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题。特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰 值已经达到500的时候,那你的程序执行离崩溃的边缘也不远了。非常多小站点的开发者一開始都将注意力放在了产品需求设计上,缺忽视了程序总体性能,可扩 展性等方面的考虑,结果眼看着訪问量一天天网上爬,可突然发现有一天站点由于訪问量过大而崩溃了。到时候哭都来不及。所以我们一定要未雨绸缪。在数据库还 没罢工前。想方设法给它减负。这也是这篇文章的主要议题。
大家都知道,当有一个request过来后。webserver交给appserver,app处理并从db中存取相关数据,但db存取的花费是相当高昂的。特 别是每次都取同样的数据,等于是让数据库每次都在做高耗费的无用功。数据库假设会说话。肯定会发牢骚,你都问了这么多遍了,难道还记不住吗?是啊,假设 app拿到第一次数据并存到内存里,下次读取时直接从内存里读取,而不用麻烦数据库,这样不就给数据库减负了?并且从内存取数据必定要比从数据库媒介取快 非常多倍,反而提升了应用程序的性能。
因此,我们能够在web/app层与db层之间加一层cache层,主要目的:1. 降低数据库读取负担;2. 提高数据读取速度。并且,cache存取的媒介是内存。而一台server的内存容量一般都是有限制的,不像硬盘容量能够做到TB级别。
所以。能够考虑採用分布 式的cache层。这样更易于破除内存容量的限制。同一时候又添加了灵活性。
Memcached 介绍
Memcached是开源的分布式cache系统,如今非常多的大型web应用程序包含 facebook,youtube,wikipedia。yahoo等等都在使用memcached来支持他们每天数亿级的页面訪问。
通过把cache层 与他们的web架构集成,他们的应用程序在提高了性能的同一时候,还大大减少了数据库的负载。
详细的memcached资料大家能够直接从它的官方站点[1]上得到。这里我就简单给大家介绍一下memcached的工作原理:
Memcached处理的原子是每个(key,value)对(下面简称kv对)。key会通过一个hash算法转化成hash-key,便于查找、对照以及做到尽可能的散列。同一时候,memcached用的是一个二级散列。通过一张大hash表来维护。
Memcached有两个核心组件组成:服务端(ms)和client(mc),在一个memcached的查询中,mc先通过计算key的hash值来 确定kv对所处在的ms位置。
当ms确定后,client就会发送一个查询请求给相应的ms,让它来查找确切的数据。
由于这之间没有交互以及多播协议,所以 memcached交互带给网络的影响是最小化的。
举例说明:考虑下面这个场景,有三个mc各自是X,Y,Z,还有三个ms各自是A,B,C:
设置kv对 X想设置key=”foo”,value=”seattle” X拿到ms列表,并对key做hash转化,依据hash值确定kv对所存的ms位置 B被选中了 X连接上B,B收到请求,把(key=”foo”,value=”seattle”)存了起来
获取kv对 Z想得到key=”foo”的value Z用同样的hash算法算出hash值,并确定key=”foo”的值存在B上 Z连接上B,并从B那边得到value=”seattle” 其它不论什么从X。Y,Z的想得到key=”foo”的值的请求都会发向B
Memcachedserver(ms)
内存分配
默认情况下,ms是用一个内置的叫“块分配器”的组件来分配内存的。舍弃c++标准的malloc/free的内存分配。而採用块分配器的主要目的 是为了避免内存碎片,否则操作系统要花费很多其它时间来查找这些逻辑上连续的内存块(实际上是断开的)。用了块分配器,ms会轮流的对内存进行大块的分配,并 不断重用。当然因为块的大小各不同样。当数据大小和块大小不太相符的情况下。还是有可能导致内存的浪费。
同一时候,ms对key和data都有对应的限制,key的长度不能超过250字节,data也不能超过块大小的限制 --- 1MB。 由于mc所使用的hash算法,并不会考虑到每一个ms的内存大小。理论上mc会分配概率上等量的kv对给每一个ms,这样假设每一个ms的内存都不太一样。那 可能会导致内存使用率的减少。所以一种替代的解决方式是。依据每一个ms的内存大小。找出他们的最大公约数,然后在每一个ms上开n个容量=最大公约数的 instance,这样就等于拥有了多个容量大小一样的子ms。从而提供总体的内存使用率。
缓存策略
当ms的hash表满了之后,新的插入数据会替代老的数据。更新的策略是LRU(近期最少使用),以及每一个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为參数传给ms的。
同一时候ms採用是偷懒替代法。ms不会开额外的进程来实时监測过时的kv对并删除。而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了。才会进行清除动作。
缓存数据库查询 如今memcached最流行的一种使用方式是缓存数据库查询,以下举一个简单样例说明:
App须要得到userid=xxx的用户信息,相应的查询语句类似:
“SELECT * FROM users WHERE userid = xxx”
App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,假设有,返回数据;假设没有,App会从数据库中读取数据。并调用cache的add函数,把数据增加cache中。
当取的数据须要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。
从上面的样例我们也能够发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。当然我们可 以通过定时器方式记录下cache中数据的失效时间,时间一过就会激发事件对cache进行更新,但这之间总会有时间上的延迟。导致app可能从 cache读到脏数据,这也被称为狗洞问题。(以后我会专门描写叙述研究这个问题)
数据冗余与故障预防
从设计角度上,memcached是没有数据冗余环节的,它本身就是一个大规模的高性能cache层,增加数据冗余所能带来的仅仅有设计的复杂性和提高系统的开支。
当一个ms上丢失了数据之后。app还是能够从数据库中取得数据。
只是更慎重的做法是在某些ms不能正常工作时,提供额外的ms来支持cache。这样就不会由于app从cache中取不到数据而一下子给数据库带来过大的负载。
同一时候为了降低某台ms故障所带来的影响,能够使用“热备份”方案,就是用一台新的ms来代替有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据又一次装载一遍。
第二种方式。就是提高你ms的节点数,然后mc会实时侦查每一个节点的状态。假设发现某个节点长时间没有响应,就会从mc的可用server列表里 删除,并对server节点进行又一次hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好 能和“热备份”方案结合使用。就能够使故障造成的影响最小化。
Memcachedclient(mc)
Memcachedclient有各种语言的版本号供大家使用。包含java。c。php,.net等等。详细可參见memcached api page[2]。 大家能够依据自己项目的须要,选择合适的client来集成。
缓存式的Web应用程序架构 有了缓存的支持。我们能够在传统的app层和db层之间增加cache层,每一个appserver都能够绑定一个mc。每次数据的读取都能够从ms中取得,假设 没有,再从db层读取。而当数据要进行更新时。除了要发送update的sql给db层。同一时候也要将更新的数据发给mc。让mc去更新ms中的数据。
如果今后我们的数据库能够和ms进行通讯了,那能够将更新的任务统一交给db层。每次数据库更新数据的同一时候会自己主动去更新ms中的数据,这样就能够进一步降低app层的逻辑复杂度。例如以下图:
只是每次我们假设没有从cache读到数据。都不得不麻烦数据库。
为了最小化数据库的负载压力,我们能够部署数据库复写,用slave数据库来完毕读取操作,而master数据库永远仅仅负责三件事:1.更新数据;2.同步slave数据库;3.更新cache。例如以下图:
以上这些缓存式web架构在实际应用中被证明是能有效并能极大地减少数据库的负载同一时候又能提高web的执行性能。
当然这些架构还能够依据详细的应用环境进行变种,以达到不同硬件条件下性能的最优化。
Memcache应用场景介绍的更多相关文章
- Memcache应用场景介绍,说明[zz]
转于:http://www.cnblogs.com/literoad/archive/2012/12/23/2830178.html 面临的问题 对于高并发高访问的 Web应用程序来说,数据库存取瓶颈 ...
- Memcache应用场景介绍,说明
面临的问题 对于高并发高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题.特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰 值已经达到500的时候,那你的程序运行离崩溃的边 ...
- 消息中间件activemq的使用场景介绍(结合springboot的示例)
一.消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构.是大型分布式系统不可缺少的中间件. 目前在生产环境,使 ...
- memcache 应用场景
一..memcache应用场景 1.应用场景一: 缓解数据库压力,提高交互速度.它的一个总原则是将经常需要从数据库读取的数据缓存在memcached中.这些数据也分为几类: (1).经常被读取并且实时 ...
- Redis 中 5 种数据结构的使用场景介绍
这篇文章主要介绍了Redis中5种数据结构的使用场景介绍,本文对Redis中的5种数据类型String.Hash.List.Set.Sorted Set做了讲解,需要的朋友可以参考下 一.redis ...
- 从Client应用场景介绍IdentityServer4(五)
原文:从Client应用场景介绍IdentityServer4(五) 本节将在第四节基础上介绍如何实现IdentityServer4从数据库获取User进行验证,并对Claim进行权限设置. 一.新建 ...
- 从Client应用场景介绍IdentityServer4(四)
原文:从Client应用场景介绍IdentityServer4(四) 上节以对话形式,大概说了几种客户端授权模式的原理,这节重点介绍Hybrid模式在MVC下的使用.且为实现IdentityServe ...
- 从Client应用场景介绍IdentityServer4(三)
原文:从Client应用场景介绍IdentityServer4(三) 在学习其他应用场景前,需要了解几个客户端的授权模式.首先了解下本节使用的几个名词 Resource Owner:资源拥有者,文中称 ...
- 从Client应用场景介绍IdentityServer4(一)
原文:从Client应用场景介绍IdentityServer4(一) 一.背景 IdentityServer4的介绍将不再叙述,百度下可以找到,且官网的快速入门例子也有翻译的版本.这里主要从Clien ...
随机推荐
- freemarker list集合去重,实现hashset
在freemarker中没有提供去重的方法,虽然有提供定义hash的方法,如:<#assign myHash = { "name": "mouse", & ...
- ie8兼容性
ie8下不支持css的nth-child()样式解决方法一:使用jQuery的nth-child()方法例:$(".ability-head-list ul li:nth-child(1) ...
- Map容器之热血格斗场
3343:热血格斗场 总时间限制: 1000ms 内存限制: 65536kB 描述 为了迎接08年的奥运会,让大家更加了解各种格斗运动,facer新开了一家热血格斗场.格斗场实行会员制,但是新来的 ...
- oracle数字返回为字符串时小时点前面的0缺失的问题
SELECT 0.001||'' from dual UNION SELECT TO_CHAR(0.001||'','fm999990.99999') from dual;
- java中的编译时与运行时
----?基础知识 -- 编译时 编译器将源代码翻译成机器能够读懂的代码,如java中就是翻译成jvm能够读懂的字节码文件.简单说,编译时就是机器帮我们检查代码是否有出现语法错误,关键字写错之类的 ...
- c++_分巧克力(75分)
#include <iostream> using namespace std; int n,k; ],w[]; bool fen(int bian){ ; ;i<n;i++){ c ...
- go语言碎片整理之标准库log
log Go语言内置的log包实现了简单的日志服务.本文介绍了标准库log的基本使用. 使用Logger log包定义了Logger类型,该类型提供了一些格式化输出的方法.本包也提供了一个预定义的“标 ...
- python012 Python3 编程第一步
Python3 编程第一步在前面的教程中我们已经学习了一些 Python3 的基本语法知识,下面我们尝试来写一个斐波纳契数列.实例如下: #!/usr/bin/python3 # Fibonacci ...
- 【转】关于大型网站技术演进的思考(十三)--网站静态化处理—CSI(5)
讲完了SSI,ESI,下面就要讲讲CSI了 ,CSI是浏览器端的动静整合方案,当我文章发表后有朋友就问我,CSI技术是不是就是通过ajax来加载数据啊,我当时的回答只是说你的理解有点片面,那么到底什么 ...
- 简单的Fleury算法模板
假设数据输入时采用如下的格式进行输入:首先输入顶点个数n和边数m,然后输入每条边,每条边的数据占一行,格式为:u,v,表示从顶点u到顶点v的一条有向边 这里把欧拉回路的路径输出了出来: 手写栈: #i ...