PHP中的九大缓存技术
1、全页面静态化缓存也就是将页面全部生成html静态页面,用户访问时直接访问的静态页面,而不会去走php服务器解析的流程。此种方式,在CMS系统中比较常见,比如dedecms;
一种比较常用的实现方式是用输出缓存:
2、页面部分缓存该种方式,是将一个页面中不经常变的部分进行静态缓存,而经常变化的块不缓存,最后组装在一起显示;可以使用类似于ob_get_contents的方式实现,也可以利用类似ESI之类的页面片段缓存策略,使其用来做动态页面中相对静态的片段部分的缓存(ESI技术,请baidu,此处不详讲)。
该种方式可以用于如商城中的商品页;
3、数据缓存顾名思义,就是缓存数据的一种方式;比如,商城中的某个商品信息,当用商品id去请求时,就会得出包括店铺信息、商品信息等数据,此时就可以将这些数据缓存到一个php文件中,文件名包含商品id来建一个唯一标示;下一次有人想查看这个商品时,首先就直接调这个文件里面的信息,而不用再去数据库查询;其实缓存文件中缓存的就是一个php数组之类;
Ecmall商城系统里面就用了这种方式;
4、查询缓存其实这跟数据缓存是一个思路,就是根据查询语句来缓存;将查询得到的数据缓存在一个文件中,下次遇到相同的查询时,就直接先从这个文件里面调数据,不会再去查数据库;但此处的缓存文件名可能就需要以查询语句为基点来建立唯一标示;
按时间变更进行缓存
其实,这一条不是真正的缓存方式;上面的2、3、4的缓存技术一般都用到了时间变更判断;就是对于缓存文件您需要设一个有效时间,在这个有效时间内,相同的访问才会先取缓存文件的内容,但是超过设定的缓存时间,就需要重新从数据库中获取数据,并生产最新的缓存文件;比如,我将我们商城的首页就是设置2个小时更新一次;
5、按内容变更进行缓存这个也并非独立的缓存技术,需结合着用;就是当数据库内容被修改时,即刻更新缓存文件;比如,一个人流量很大的商城,商品很多,商品表必然比较大,这表的压力也比较重;我们就可以对商品显示页进行页面缓存;
当商家在后台修改这个商品的信息时,点击保存,我们同时就更新缓存文件;那么,买家访问这个商品信息时,实际问的是一个静态页面,而不需要再去访问数据库;
试想,如果对商品页不缓存,那么每次访问一个商品就要去数据库查一次,如果有10万人在线浏览商品,那服务器压力就大了;
6、内存式缓存提到这个,可能大家想到的首先就是Memcached;memcached是高性能的分布式内存缓存服务器。 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
它就是将需要缓存的信息,缓存到系统内存中,需要获取信息时,直接到内存中取;比较常用的方式就是 key–>value方式;
7、apache缓存模块apache安装完以后,是不允许被cache的。如果外接了cache或squid服务器要求进行web加速的话,就需要在htttpd.conf里进行设置,当然前提是在安装apache的时候要激活mod_cache的模块。
安装apache时:./configure –enable-cache –enable-disk-cache –enable-mem-cache
8、php APC缓存扩展Php有一个APC缓存扩展,windows下面为php_apc.dll,需要先加载这个模块,然后是在php.ini里面进行配置:
9、Opcode缓存我们知道,php的执行流程可以用下图来展示:
首先php代码被解析为Tokens,然后再编译为Opcode码,最后执行Opcode码,返回结果;所以,对于相同的php文件,第一次运行时可以缓存其Opcode码,下次再执行这个页面时,直接会去找到缓存下的opcode码,直接执行最后一步,而不再需要中间的步骤了。比较知名的是XCache、Turck MM Cache、PHP Accelerator等。
微服务架构下,如何克服分布式事务难题?
【摘要】 分布式事务已经成为微服务落地最大的阻碍,也是最具挑战性的一个技术难题。 为此,本文将深入和大家探讨微服务架构下,分布式事务的各种解决方案。
简而言之,微服务架构的系统是一个分布式的系统,按业务进行划分为独立的服务单元,解决单体系统的不足,同时也满足越来越复杂的业务需求。每个微服务仅关注于完成一件任务并很好地完成该任务。
1. 将复杂的业务拆分成多个小的业务,每个业务拆分成一个服务,将复杂的问题简单化。利于分工,降低新人的学习成本。
2. 微服务系统是分布式系统,业务与业务之间完全解耦,随着业务的增加可以根据业务再拆分,具有极强的横向扩展能力。
3. 服务间采用 HTTP 协议通信,服务与服务之间完全独立。每个服务可以根据业务场景选取合适的编程语言和数据库。
4. 服务独立部署,每个服务的修改和部署对其他服务没有影响。
虽然微服务有以上的优势,但是微服务实践仍处于探索阶段,很多中小型互联网公司,鉴于经验、技术实力等问题,微服务落地比较困难。著名架构师Chris Richardson指出,目前微服务主要存如下几方面困难:
1. 单体应用拆分为分布式系统后,进程间的通讯机制和故障处理措施变的更加复杂。
2. 系统微服务化后,一个看似简单的功能,内部可能需要调用多个服务并操作多个数据库实现,服务调用的分布式事务问题变的非常突出。
3. 微服务数量众多,其测试、部署、监控等都变的更加困难。
随着RPC框架的成熟,第一个问题已经逐渐得到解决。例如Dubbo可以支持多种通讯协议,Spring Cloud可以非常好的支持restful调用。对于第三个问题,随着Docker、DevOps技术的发展以及各公有云PaaS平台自动化运维工具的推出,微服务的测试、部署与运维会变得越来越容易。
而对于第二个问题,现在还没有通用方案很好的解决微服务产生的事务问题。分布式事务已经成为微服务落地最大的阻碍,也是最具挑战性的一个技术难题。下面将深入和大家探讨微服务架构下,分布式事务的各种解决方案。
事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性:
原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性。
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。数据库事务隔离级别由低到高依次为Read uncommitted、Read committed、Repeatable 、Serializable。
持久性(Durability):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
银行转账业务是一个典型分布式事务场景,通常包括以下三种情况:
A. 支行内转账:同一银行的相同支行内转账
B. 行内转账:同一银行的不同支行间转账
C. 跨行转账:不同银行的系统进行转账
对于传统集中式架构,A、B通常为本地事务,C为分布式事务。业务微服务改造后,转入、转出通常为不同的微服务,同一个微服务也通常运行于不同实例中。A可能变成一个分布式事务,也可能通过一些方法规避,在本地事务内完成。B和C很难规避,只能是分布式事务。
微服务最佳实践建议尽量规避分布式事务,但是在很多业务场景(比如上面的B、C转账场景),分布式事务是一个绕不开的技术问题。
为了解决分布式系统一致性问题,前人在性能和数据一致性的反反复复权衡过程中总结了许多典型的协议和算法。其中,最常用的是两阶提交协议(2 Phase Commitment Protocol)。
交易中间件与数据库通过 XA 接口规范,使用两阶段提交来完成一个全局事务, XA 规范的基础是两阶段提交协议。
第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;第二阶段是执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。
两阶段提交方案应用非常广泛,典型商用软件包括Oracle Tuxedo和IBM CICS。它的优点是对业务代码侵入较低,但缺点也很明显:
性能低下:由于 XA 协议自身的特点,它会造成事务资源长时间得不到释放,锁定周期长,而且在应用层上面无法干预,数据并发冲突高的场景性能很差。
单点问题:协调者在整个两阶段提交过程中扮演着举足轻重的作用,一旦协调者所在服务器宕机,就会影响整个数据库集群的正常运行。比如在第二阶段中,如果协调者因为故障不能正常发送事务提交或回滚通知,那么参与者们将一直处于阻塞状态。
同步阻塞:两阶段提交执行过程中,所有的参与者都需要听从协调者的统一调度,期间处于阻塞状态而不能从事其他操作,效率及其低下。
因此,两阶段提交方案在互联网业务中很少使用,无法满足高并发需求。
为了这个弥补这种方案带来性能低的问题,大家又想出了很多种方案来解决,通过在应用层做文章,即入侵业务的方式,比较典型的是TCC 方案和基于可靠消息的最终一致性方案。
TCC事务模型在电商、金融领域落地较多。TCC方案其实是两阶段提交的一种改进。其将整个业务逻辑的每个分支显式的分成了Try、Confirm、Cancel三个操作。Try部分完成业务的准备工作,confirm部分完成业务的提交,cancel部分完成事务的回滚。基本原理如下图所示。
事务开始时,业务应用会向事务协调器注册启动事务。之后业务应用会调用所有服务的try接口,完成一阶段准备。之后事务协调器会根据try接口返回情况,决定调用confirm接口或者cancel接口。如果接口调用失败,会进行重试。
TCC方案让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能,比如华为分布式事务中间件DTM性能极高,普通配置服务器可以支持全局事务1万+ TPS,分支事务3万+ TPS。 当然TCC方案也有不足之处,集中表现在以下两个方面:
业务侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。
实现难度较大。为了满足一致性的要求,要充分考虑幂等操作,允许重复执行,也要防止资源悬挂,做好并发访问控制和数据可见性控制等。
上述原因导致TCC方案大多被研发实力较强、有迫切需求的大公司所采用。微服务倡导服务的轻量化,而TCC方案中很多事务的处理逻辑需要应用自己编码实现,复杂且开发量大。
消息一致性方案是通过消息中间件保证上下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个本地事务中,保证本地操作和消息发送要么两者都成功或者都失败。下游应用向消息系统订阅该消息,收到消息后执行相应操作。
消息最终一致方案从本质上讲是将分布式事务转换为两个本地事务,然后依靠下游业务的重试机制达到最终一致性。基于消息的最终一致性方案对应用侵入性也很高,应用需要进行大量业务改造,成本非常高。
入侵代码的方案是基于现有情形“迫不得已”才推出的解决方案,实际上它们实现起来非常不优雅,比如TCC,一个事务的调用通常伴随而来的是对该事务接口增加一系列的反向操作,提交逻辑必然伴随着回滚的逻辑,这样的代码会使得项目非常臃肿,维护成本高。
针对上面所说的分布式事务解决方案的痛点,很显然,我们理想的分布式事务解决方案肯定是性能要好而且要对业务无侵入,业务层无需关心分布式事务机制的约束,做到事务与业务分离,也就是本文所重点推荐的非侵入事务。
非侵入事务典型架构如下图所示:
事务核心组件包括:
Transaction Coordinator (TC): 事务协调器,分布式事务大脑,产生和维护全局事务、分支事务,推进事务提交与回滚的二阶段处理。TC Server以集群形式提供事务协调能力。
Transaction Manager (TM): 定义全局事务的边界,与事务协调器通信以开启、提交或回滚全局事务。
Resource Manager (RM): 资源管理器,管理分支事务处理的资源,与事务协调器通信以开启、结束事务分支,并接收事务协调器指令完成二阶段分支事务提交或回滚。
Lock Server (LS): 分布式锁服务器,可以通过它对进行中的分布式事务所操作的资源查询、加锁、放锁。
一个分布式事务称为一个全局事务,下面挂若干个分支事务,一个分支事务是一个满足 ACID 的本地事务。非侵入事务的核心思想是资源管理器拦截业务SQL,对其解析并做额外的一些数据处理,产生undo log并保存,一旦发生全局事务回滚,通过各个分支事务对应的undo log完成所有分支事务回滚。
大家很容易想到,两个全局事务并行修改了相同数据,可能会造成根据undo log完成回滚产生数据错误。解决的方法是通过Lock Server对事务所修改数据加锁,全局事务提交后立即放锁,全局事务回滚则等待分支事务回滚完成放锁。
典型分布式事务主要执行步骤如下:
1. TM请求TC开始新的全局事务,TC创建全局事务并返回全局事务ID(XID)。
2. 根据XID构建事务上下文,通过微服务的调用链传播。
3. RM发现自己处于事务上下文,得到全局事务ID并解析SQL,产生undo log和分布式事务锁数据,请求TC创建分支事务。
4. TC 通过LS加锁,加锁成功后创建分支事务ID并返回。
5. RM 把分支事务ID与undo log关联,与业务原始SQL在一个本地事务内提交。
6. 重复3~5,为全局事务范围内的每个本地事务创建一个分支事务。
7. 如果全局事务边界内没有任何异常,则TM请求TC提交全局事务;如果有异常,则TM请求TC回滚全局事务。
8. TC标记全局事务状态,如果为提交则立即通过LS放锁。推进XID所对应全局事务下的所有分支事务进行二阶段处理,发送请求到RM。
9. RM完成分支事务的提交或回滚,并返回状态到TC。
10. TC对完成回滚的分支通过LS放锁。所有分支完成后,返回全局事务处理结果到TM。
二阶段事务处理比较关键,在此重点说明一下。
如果全局事务状态为提交,则对每个分支发起分支提交,流程如下图所示:
RM收到分支事务提交请求,先保存分支事务的ID在队列中并返回。一个线程定时从队列中取出一批分支事务ID,构建SQL批量删除所对应的undo log日志。分支事务提交可以异步批量处理,是因为全局事务已经提交,undo log作为中间状态已经不再重要,只要定期清理即可。
如果全局事务状态为回滚或超时,则对每个分支发起分支回滚,流程如下图所示:
RM收到分支事务回滚请求,开启一个本地事务,通过分支ID找到对应的undo log,构建回滚SQL语句并执行,删除undo log,然后提交本地事务。如果顺利完成,TC收到响应后通过LS清理该分支所占用资源。
非侵入事务相比XA两阶段提交一个重要性能优势在于锁定资源时间更短。实际业务中,我们知道绝大多数事务状态为提交,很少比例为回滚。对于XA来说,无论是提交还是回滚,资源都是在二阶段释放。对本文所介绍的非侵入事务来说,提交状态的全局事务,二阶段没有必要拿锁,只有少比例的回滚状态的全局事务,才需要在二阶段放锁。
非侵入事务不受限于数据库XA接口,实现完全可控。TC、RM、LS这些关键组件对性能影响很大,良好的设计、实现可以取得非常高的性能。非侵入式事务实践证明,它可以轻松满足绝大多数高并发业务场景的性能需求。
华为云Stack为某运营商核心业务系统分布式事务改造,该客户业务在月初充值、扣费业务高峰期等常见的并发场景时,对分布式系统提出挑战:
- 高并发的分布式事务访问账户表,XA两阶段提交由于加锁时间长,严重影响业务。整体性能要求达1000+ TPS,传统或开源分布式事务难以满足高可用性与高性能要求。
- XA事务与其他数据库操作的一致性问题。需要把XA事务作为DTM TCC事务的一个分支,将别的数据库操作是另外的分支。
华为云Stack混合云解决方案分布式事务中间件DTM通过一系列创新技术,提供高性能、高可用、高可靠、高安全、低侵入、易使用的分布式事务服务,支持TCC事务和非侵入事务两种模型,助力企业微服务化改造,优雅地解决分布式系统下数据一致性难题。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。