你应该了解的php缓存技术
缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。
概念
缓存
所谓的缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。
- 1、通过文件缓存;
- 顾名思义文件缓存是指把数据存储在磁盘上,不管你是以XML格式,序列化文件DAT格式还是其它文件格式;
- 2、内存缓存;
- 也就是创建一个静态内存区域,将数据存储进去,例如我们B/S架构的将数据存储在Application中或者存储在一个静态Map中。
- 3、分布式缓存机制;
- 可能存在跨进程,跨域访问缓存数据
对于分布式的缓存,此时因为缓存的数据是放在缓存服务器中的,或者说,此时应用程序需要跨进程的去访问分布式缓存服务器。
PHP缓存
PHP缓存包括PHP编译缓存和PHP数据缓存两种。
PHP是一种解释型语言,属于边编译边运行的那种。这种运行模式的优点是程序修改很方便,但是运行效率却很低下。
PHP编译缓存针对这种情况做改进处理,使得PHP语言只要运行一次,就可以把程序的编译结果缓存起来。
【PHP编译缓存】
PHP是一种解释型语言,在PHP语言执行代码的时候,需要下面两步:
- 1、编译过程。
- PHP读取文件,并编译该文件,然后生成能够在Zend Engine虚拟机上执行的中间码。
- 2、执行过程。
- PHP直接执行中间码。
效率低下的场景:
- 1、即使PHP代码文件没有发生改变,也会被PHP重新编译。
- 2、如有引用文件,PHP也要花费时间重新编译这些被引用的文件。
因此,需要PHP编译缓存工具对PHP程序的编译结果做缓存处理。
这样,PHP程序只要编译一次,就不要重新再做无意义的编译了。
【PHP数据缓存】
PHP的数据缓存包括针对数据库数据进行缓存和针对PHP模板数据进行缓存。
针对数据库数据进行缓存的工具有memcache等。
针对PHP模板数据进行缓存的工具主要有smarty等。
优势
提升性能
绝大多数情况下,select 是出现性能问题最大的地方。
- 一方面,select 会有很多像 join、group、order、like 等这样丰富的语义,而这些语义是非常耗性能的;
- 另一方面,大多 数应用都是读多写少,所以加剧了慢查询的问题。
分布式系统中远程调用也会耗很多性能,因为有网络开销,会导致整体的响应时间下降。
为了挽救这样的性能开销,在业务允许的情况(不需要太实时的数据)下,使用缓存是非常必要的事情。
缓解数据库压力
当用户请求增多时,数据库的压力将大大增加,通过缓存能够大大降低数据库的压力。
缓存的适用场景
- 对于数据实时性要求不高
- 对于一些经常访问但是很少改变的数据,读明显多于写,适用缓存就很有必要。
- 比如一些网站配置项。
- 对于性能要求高
- 比如一些秒杀活动场景。
生存期
生存期是指数据保持有效性的时间区间,也就是从创建到移除的时间间隔。
通常的生存期有以下几种:
-
永久状态Permanent State——应用程序使用的永久数据;
-
进程状态Process State——只在进程周期内有效;
-
会话状态Session State——和特定的用户会话有关;
-
消息状态Message State——处理某个消息的时间内有效;
缓存技术
【memcached】
Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。
Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。
Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果。
Memcached简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的很多问题。它的API兼容大部分流行的开发语言。
本质上,它是一个简洁的key-value存储系统。
一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
特征
memcached作为高速运行的分布式缓存服务器,具有以下的特点:
- 协议简单
- 基于libevent的事件处理
- 内置内存存储方式
- memcached不互相通信的分布式
支持的语言
许多语言都实现了连接memcached的客户端,其中以Perl、PHP为主。
仅仅memcached网站上列出的有:
Perl
PHP
Python
Ruby
C#
C/C++
Lua
……
原生PHP使用memcached示例:
error_reporting(E_ALL & ~E_NOTICE);
$mc = new \Memcached();
$mc->addServer("XXXX.memcache.rds.aliyuncs.com", 11211);
$mc->set("foo", "Hello!");
$mc->set("bar", "Memcached...");
$arr = array(
$mc->get("foo"),
$mc->get("bar")
);
var_dump($arr);
【redis】
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis 优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Redis与其他key-value存储有什么不同?
- Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
- Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
lumen下使用memcached
Laravel 为各种缓存系统提供了统一的 API,缓存配置位于 .env 文件中,在该文件中你可以指定应用默认使用哪个缓存驱动。
## 缓存配置
CACHE_DRIVER=memcached
MEMCACHED_HOST=XXXX.memcache.rds.aliyuncs.com
MEMCACHED_PORT=11211
Lumen 缓存驱动与 Laravel 缓存驱动使用了完全相同的代码。
除配置之外,在 Lumen 中使用缓存和在 Laravel 中使用缓存没有区别;
配置文件:
如图可看出,lumen自带的配置框架让我们直接在.env配置对应参数即可。
注意: 在使用 Cache Facade 之前,请确保在 bootstrap/app.php 文件中没有注释掉 $app->withFacades() 方法的调用。
lumen下使用redis
在使用 Lumen 的 Redis 缓存之前,你需要通过 Composer 安装 illuminate/redis (5.5.*) 包。
composer require illuminate/redis
然后,你需要在 bootstrap/app.php 文件中注册 Illuminate\Redis\RedisServiceProvider。
$app->register(Illuminate\Redis\RedisServiceProvider::class);
如果你没有在 bootstrap/app.php 文件中调用 $app->withEloquent(),那么你应该在 bootstrap/app.php 文件中调用 $app->configure(‘database’); 以确保正确加载 Redis 数据库配置。
配置文件:
可以看到,lumen自带的配置框架让我们直接在.env配置对应参数即可。
所以应该使用的.env配置如下:
## 缓存配置
CACHE_DRIVER=redis
## redis配置
REDIS_HOST=XXXX.redis.rds.aliyuncs.com
REDIS_PASSWORD=XXXX
REDIS_PORT=6379
REDIS_DB=1
使用示例
<?php
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class TestController
{
private static $_test_key = '_test_';
public function set()
{
$expire = 60 * 2;
Cache::store('redis')->put(self::$_test_key, date('Y-m-d H:i:s'), $expire);
$success = Cache::store('redis')->has(self::$_test_key);
return $success;
}
public function get()
{
$value = Cache::store('redis')->get(self::$_test_key);
return [
'key' => self::$_test_key,
'value' => $value,
];
}
}
以上,还只是帮助大家简单入门,想要了解更多相关技术,快来关注我吧,让我们成为更优秀的自己!!!