缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。

概念

缓存

所谓的缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

  • 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,
        ];
    }
}

以上,还只是帮助大家简单入门,想要了解更多相关技术,快来关注我吧,让我们成为更优秀的自己!!!