14.高性能MySQL --- 应用层优化

 

1.常见问题
	1.什么东西在消耗系统中每台主机的cpu,磁盘,网络以及内存资源
	2.应用真的需要所有获得到的数据吗
	3.应用在处理本应由数据库处理的事情吗?或者反过来。例如,在应用中统计,或者在数据库中进行复杂的字符串操作
	4.应用执行了太多的查询
	5.应用执行的查询太少了?有时候让应用做'手工关联'是个好主意,它们允许更细的粒度控制和更好有效的使用缓存,以及更少的锁争用。
	6.应用创建了没必要的mysql连接吗
	7.应用对一个mysql实例创建连接的次数太多了吗
	8.应用做了太多的'垃圾'查询
	9.应用使用连接池了吗
	10.应用是否使用了长连接
	11.应用是否在不使用的时候还保持连接打开

	长连接和连接池:
		长连接可能跟连接池有同样的副作用,因为重用的连接在这2个情况下都是有状态的。然后,连接池通常不会导致服务器连接过多,因为它们会在
	  进程间排队和共享连接。另外一方面,长连接是在每个进程基础上创建,不会在进程间共享。
	    连接池也比共享连接的方式对连接策略有更强的控制力。连接池可以配置为自动扩展,但是通常的经验是,当遇到连接池完全占满时,应该将连接
	  请求进行排队而不是扩展连接池。

2.Web 服务器的问题
	apache 通常是通过 prefox 配置来使用 mod_php,mod_perl和 mod_python 模块的。prefork 模式会为每个请求预先分配进程。因为php,perl,
  python 脚本是可以定制化的,每个进程使用50MB或100MB 内存的情况并不少见。当一个请求完成后,会释放大部分的内存给操作系统,但不是全部。apache
  会保持进程出于打开状态以备后来的请求重用。这意味着,如果下一个请求是请求静态文件,比如一个css文件,就会出现一个占用内存很大的进程来为一个很小
  的请求服务的情况。这就是apache作为一个通用web服务器很危险的原因。
    另外一个主要的问题是,如果开启了keep-alive设置,进程可能长时间处于繁忙状态。
    人们常犯的错,就是保持那么apache默认开启的模块不动。最好能够精简apache模块,移除不要的。php.ini也是。
    最差的情况是,如果用一个通用的apache配置直接用于web服务,最后很可能产生重量级的apache进程,浪费web服务器的资源。它们还可能保持大量的mysql
  连接,浪费mysql资源。
    下面是可以降低服务器负载的方法:
    不要使用apache来做静态内容服务,或者至少和动态服务使用不同的apache实例。或者使用nginx。
    1.使用缓存代理服务器,比如squid或者varnish,防止所有的请求都到达web服务器。
    2.对静态和动态内容都做过期设置。
    3.不要让apache填鸭式的服务客户端
    4.打开gzip压缩,对于现在的cpu这样代价很小
    5.不要为用于长距离连接的apache配置启用 keep-alive选项,会使得重量级的apache进程存活很久。

3.缓存
	典型的高负载应用会设置很多层缓存。缓存并不仅仅发生在服务器上,而是在每一个环节,甚至包括用户的浏览器(这就是内容过期头的用处)。通常,缓存越接近
  客户端,就越节省资源并且效率更高。从浏览器缓存提供一张图片比从web服务器的内存获取快的多,而从服务器内存读取又比从服务器的磁盘上读取好得多。
    可以把缓存设置为两大类:被动缓存和主动缓存。被动缓存除了存储和返回数据外不做任何事情。当从被动缓存请求一些内容时,要么可以得到结果,要么得到'结果
  不存在'。被动缓存的一个典型例子是memcached。
    相比之下,主动缓存会在访问未命中时做一些额外的工作。通常会将请求转发给应用的其他部分来处理生成请求,然后存储结果并返回应用。squid缓存代理服务器就
  是一个主动缓存。
    在设置应用时,通常希望缓存是主动的(也可以叫做透明的),因为它们对应用隐藏了检查---生成---存储这个逻辑过程。也可以在被动缓存的前面构建一个主动缓存。
   	
   	应用缓存:
   		应用缓存通常在同一台机器的内存中存储数据,或者通过网络存在另外一台机器的内存。因为应用可以缓存部分计算结果,所以应用层可能比更低的缓存更有效。
   	  因此,应用层缓存可以节省2方面的工作:获取数据以及基于这些数据进行计算。
   	    应用层缓存也有缺点,那就是缓存命中率可能更低。
   	    应用缓存有很多种:
   	    	1.本地缓存
   	    		这种缓存通常很小,只在进程处理请求期间存在于进程内存中。本地缓存可以有效的避免对某些资源的重复请求。这种类型的缓存技术并不复杂:通常
   	    	  只是应用代码中的一个变量或者哈希表,如静态全局变量。
   	    	2.本地共享内存缓存
   	    		这种缓存一般是中等大小(几个GB),快速,难以在多台机器间同步。它们对小型的半静态位数据比较合适。共享内存的好处是访问非常快---通常比其他
   	    	  任何远程缓存访问要快不少。
   	    	3.分布式内存缓存
   	    		常见的分布式内存缓存的例子是memcached。分布式缓存比本地共享内存缓存要大的多,增长也容易。缓存中创建的数据每一个比特只有一个副本,这样
   	    	  既不会浪费内存,也不会因为相同的数据在不同的地方而引入一致性问题。分布式内存非常适合存储共享对象。
   	    	    分布式缓存比本地共享缓存的延迟要高的多,所以最有效的使用方法是批量进行多个获取操作。分布式缓存还需要考虑怎么增加更多的节点,以及某个节点
   	    	  崩溃了怎么办。对于这2个场景,应用程序必须决定在节点间怎么分布或重分布缓存对象。当缓存集群增加或者减少一台机器,一致性缓存对避免性能问题而言
   	    	  是非常重要的。
   	    	4.磁盘上的缓存
   	    		磁盘是很慢的,所以缓存在磁盘上的最好是持久化对象,很难全部装进内存的对象,或者是静态内容。
   	    		对于磁盘上的缓存和web服务器,一个非常有用的技巧是使用404错误处理机制来捕获缓存未命中的情况。缓存失效很简单:删除文件即可。

   	缓存控制策略:
   		1.TTL(time to live, 存活时间)
   			缓存对象存储时设置一个过期时间,可以通过清理进程在达到过期时间后删除对象,或者先留着直到下次访问时再清理(清理后使用新的版本替换)。对于数据很少
   		  变更或者没有新数据的情况,这是很少的策略。
   		2.显式失效
   			如果不能接受脏数据,那么进程在更新原始数据时需要同时使缓存失效。这种策略有2个变种:写---失效和写---更新。写---失效策略很简单:只需要标记缓存
   		  数据已经过期(是否清理是可选的)。写---更新需要多做一些工作,因为在数据更新时就需要替换掉缓存。
   		3.读时失效
   			在更改旧数据时,为了避免要同时失效派生出来的脏数据,可以在缓存中保存一些信息,当从缓存中读数据时可以利用这些信息判断数据是否已经失效。很显式失效
   		  策略相比,这样做优势很大:成本固定且可以分散在不同时间内。
   		  	一种最简单的读时失效的办法是采用对象版本控制。可以在缓存中 blog_stats 对象的版本与缓存的用户版本进行比较。

   	缓存对象分层:
   		分层缓存对象读检索,失效和内存利用都有帮助。相对于只缓存对象,也可以缓存对象的id,对象的id组等通常需要一起检索的数据。
   		电商的搜索结果是这种技术的很好例子。一次搜索可能返回一个匹配产品的列表,包括名称,描述等。缓存整个列表的效率很低:其他搜索也可能包含一些相同的产品,就
   	  会导致数据重复了,并且浪费内存。这种策略也使得当一个产品价格变动时,并找出失效搜索结果变得很难,因为你必须查看每个列表,找到哪些列表包含更新过的产品。
   	    可以缓存关于搜索的最小信息,而不必缓存整个列表,例如返回结果的梳理以及列表中的产品id。然后再单独缓存每个产品。这样做可以解决2个问题:不会重复存放任何
   	  结果数据,也更容易在失效产品的粒度上去失效缓存。
   	    缺点则是,相对于一次性获取整个搜索结果,必须在缓存中检索多个对象。然后不管怎么说,为搜索缓存产品id的列表都是有效的做法。先在一个缓存命中返回产品id的列表,
   	  再使用这些id去请求缓存获得产品信息。如果缓存允许一次调用返回多个结果,第二次请求就可以返回多个产品(如memcache 的 mget()方法)。

   	预生成内容:
   		除了在应用程序级别缓存位数据,也可以在后台预先请求一些页面,并且将结果存为静态页面。如果页面是动态的,也可以预先生成页面的部分内容,然后使用像服务端包含(ssi)
   	  这样的技术创建最终页面。这有助于减少预生成内容的大小和开销,否则可能在将不同部分拼装到最终页面时,由于微小的变化产生大量的重复内容。
   	    预生成内容的好处是:
   	    	1.应用代码没有复杂的命令和未命中处理路径
   	    	2.当未命中的处理路径慢的不可接受时,这种方案可以很好的工作,因为它保证了未命中的情况永远不会发生。实际上,在设计任何类型的缓存系统,总是应该考虑未命中的
   	        路径有多慢。
   	        3.预生成内容可以避免在缓存未命中时导致的雪崩效应。
   	    缓存预生成好的内容可能占用大量空间,并且并不能总预生成所有的东西。无论是哪种情况,需要预生成的内容中最重要的那部分是那些最经常被请求,或者生成成本最高的。

   	作为基础组件的缓存:
   		缓存的加入可以使得应用压力显著增长时不需要对系统的某些部分同比增加资源投入---通常是数据库部分。因此,系统可能慢慢的对缓存非常依赖,却没有发觉。
   		例如,如果高速缓存命中率是90%,当由于某种原因失去缓存,数据库上的负载将增加到原来的10倍。

   	使用 HandlerSocket 和 Memcached:
   		相对于数据存储在Mysql中而缓存在mysql外部的缓存方案。另外一种替代方法是为mysql创建一个更快的访问路径,直接绕过使用缓存。对于小而简单的查询语句,很大一部分
   	  开销来自解析sql,检查权限,生成执行计划等。
   	    目前有2种方案可以用所谓的NoSQL方式访问mysql。
   	    1.后台进程插件,HandlerSocket
   	    2.通过 Memcached 协议访问 InnoDB

4.扩展 MySQL
	存储引擎是扩展mysql很好的方式,还可以使用存储引擎作为另一个软件的接口(Sphinx)。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值