Yii框架分布式缓存的实现方案

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 声明:本文阅读对象最好是对Yii和分布式缓存有一定了解的人群,否则理解和掌握上有一些困难,建议阅读之前做好以上两点基础准备。   YiiFramework简称Yii,读作易,代表简单(easy)、高效(efficient)、可扩展(extensible),Yii将面向对象思想以及代码的重用性发挥到了极致,尤其是在缓存的支持上,Yii是最有效率的PHP框架之一。

声明:本文阅读对象最好是对Yii和分布式缓存有一定了解的人群,否则理解和掌握上有一些困难,建议阅读之前做好以上两点基础准备。

 

YiiFramework简称Yii,读作易,代表简单(easy)、高效(efficient)、可扩展(extensible),Yii将面向对象思想以及代码的重用性发挥到了极致,尤其是在缓存的支持上,Yii是最有效率的PHP框架之一。

Yii的缓存支持封装在框架核心的caching文件夹下面,如下图是Yii支持的缓存存储介质。

 

 

如果要做跨Session和请求的分布式缓存,可以选用CFileCache,如果要做跨WebServer的分布式缓存,就必须用CMemCache或CRedisCache缓存。

 

1.跨Session和请求分布式缓存处理方案(只有一台Web服务器、利用缓存依赖实现缓存实时更新)

 

Yii缓存支持需要在项目的主配置文件添加相应的配置支持。

       'components'=>array(

          //设置缓存
         'cache'=>array(
             'class'=>'CFileCache',
          ),
       ),


Yii中不管缓存介质是磁盘、数据库还是内存,赋值和取值都是统一的,这样的话,当我们有更换缓存介质的时候就可以改一下主配置文件,程序代码一点都不用动,这也是Yii将代码重用性发挥到极致的一个很好体现。

 

      A.缓存的赋值:


    Yii::app()->cache->set(key,value,过期时间,依赖条件);


下面举一个具体调用案例:


       $products=['id'=>1,'name'=>'茅台酒'];

        Yii::app()->cache->set('product',
                       $products,
                       30,
                       newCGlobalStateCacheDependency('version')
        );


      上面是一个常用的案例,我们将'product'作为key,$products数组当做value,过期时间为30秒(若永不过期此处填0),同时依赖全局缓存变量'version'这个值。

 

设置缓存依赖后,当'version'的值发生变化后,缓存过期,30秒后缓存过期,这两个条件有一个成立,缓存都过期。

 

      B.缓存值的获取

 

   Yii::app()->cache->get(key);

下面举一个具体调用案例:

 

跨Session和请求分布式缓存的实现方案Demo:

 

读取线程代码:


    $products=Yii::app()->cache->get('product');
    //没有读取到缓存
    if($products===false)
    {
       $pro=Yii::app()->db;
       $products=$pro->createCommand("select*from{{product}}")->query();

       //设置缓存永不过期,同时依赖于全局变量'version'
       Yii::app()->cache->set('product',
                              $products,
                              0,
                              newCGlobalStateCacheDependency('version')
        );
       echo "从数据库获取<br/>";
     }
     echo json_encode($products);

 

写线程代码:


    $pro=Yii::app()->db;

    $command=$pro->createCommand("INSERTINTO{{product}}(`name`,`color`,`version`)VALUES('依赖','黑色',1)");

    $command->execute();

    //设置缓存依赖,让缓存过期

    $version=Yii::app()->getGlobalState('version');

    Yii::app()->setGlobalState('version',++$version);

 

上面的业务逻辑如下图:

 



读线程每次获取缓存的时候都会验证一下缓存依赖是否值发生变化,如果缓存依赖值变化了就获取不到缓存,获取不到缓存就会去数据库查询结果,查询到结果后,重新设置缓存;如果缓存依赖值没有发生变化,直接获取缓存,不再连接数据库并将值返回给浏览器,这样读线程完成了任务。

 

写线程直接操作数据库,将数据更新到数据库,然后他只需要更新Denp缓存依赖就可以返回浏览器了,当然,写线程也可以直接清除对应的缓存,这样写线程完成任务。

 

当你想更新缓存介质的时候,如Memcached做分布式缓存介质,前提是web服务器安装php的memcached扩展,在web程序内只需要在主配置文件中做如下修改:


    'components'=>array(
       //设置缓存
       'cache'=>array(
          'class'=>'CMemCache',
          'servers'=>array(
             array('host'=>'192.168.1.16','port'=>11211,'weight'=>60),
             array('host'=>'192.168.1.16','port'=>11212,'weight'=>40),
           ),
        ),
    ),


 

2.跨Web服务器分布式缓存处理方案

跨Web服务器的分布式缓存就得借助于Memcached或Redis了,如下图:

 

 


浏览器将读/写请求交给反向代理Nginx或者F5硬件,再由Nginx将请求分发给各自的Web服务器,各自Web服务器共享缓存服务器。

 

上图是利用Cache Server来实现的分布式缓存实时更新,处理流程:

1号读线程开始请求缓存,请求不到,读取数据库,设置缓存,将查询结果返回给浏览器;2号读线程,请求缓存,请求到缓存,将结果返回给浏览器;写线程直接操作数据库,删除缓存,返回浏览器;1号读线程读不到缓存,读取数据库,设置缓存,将查询结果返回给浏览器。

 

读线程代码:


/**读线程
*@return mixed
*/
public function actionWide()
{
    $products=$this->getCache();
    if(!$products)
    {
       $products=$this->getProducts();
       $this->setCache($products);
       echo "没有获取到缓存,从数据库读取数据。<br/>";
    }
    echo json_encode($products);
}

/**从缓存中读取数据
*@return mixed
*/
private function getCache()
{
     return Yii::app()->cache->get('product');
}

/**从数据库读取数据
*@return mixed
*/
private function getProducts()
{
     $pro=Yii::app()->db;
     $products=$pro->createCommand("select*from{{product}}")->query();
     $products=$products->readAll();
     return $products;
}

/**
*更新缓存
*/
private function setCache($products)
{
    Yii::app()->cache->set('product',$products);
}

写线程代码:


 

/**
*模拟写操作
*/
public function actionWrite()
{
    $pro=Yii::app()->db;
    $command=$pro->createCommand("INSERTINTO{{product}}(`name`,`color`,`version`)VALUES('依赖','黑色',1)");
    $command->execute();
    $this->delCache('product');
    echo "写成功";
}

/**根据键值删除缓存
*@param$key键值
*/
private function delCache($key)
{
    Yii::app()->cache->delete($key);
}

如果你想用Redis或Memcached做缓存,最好用Linux做缓存服务器,连接Web服务器就不做限制了,但是有一点,如果你想用Redis做缓存,或者Web服务器安装php对Redis的扩展,或者去Yii官网下载Yii对Redis的支持扩展,否则Yii不是不能利用Redis做缓存的,也可以在这里下载,这是我下好的。

RedisCache

下载解压放在extensions目录,在主配置文件里做如下修改:


'components'=>array(
    //设置缓存
    'cache'=>array(
        'class'=>'ext.redis.CRedisCache',
        'servers'=>array(
            array('host'=>'192.168.1.16','port'=>6379,),
         ),
     'keyPrefix'=>'',
    ),
),


最后补充一下,为什么加这个keyPrefix配置,因为,如果你想用telnet通过key获取memcached或者Redis中的缓存value,是获取不到的,因为Yii框架给key会加上默认前缀,如果你在这里配置了,Yii框架就不会再对key进行处理了,这样你就可以通过telnet获取到缓存数据了。

 

好了,就到这里了。

 

 

 

 

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
机器学习/深度学习 分布式计算 数据处理
分布式计算框架:并行力量的交响乐章
分布式计算框架如Apache Spark解决单机计算挑战,通过拆分任务到多机并行处理提升效率。Spark以其内存计算加速处理,支持批处理、查询、流处理和机器学习。以下是一个PySpark统计日志中每日UV的示例,展示如何利用SparkContext、map和reduceByKey进行数据聚合分析。这些框架的运用,正改变大数据处理领域,推动数据分析和机器学习的边界。【6月更文挑战第18天】
100 2
|
1月前
|
负载均衡 监控 Go
使用Golang框架构建分布式系统
本文探讨了使用Golang构建分布式系统的方法。Golang因其高效、简洁的语法和并发支持成为理想的开发语言。文中列举了几个常用的Golang框架,如Echo、Gin、gRPC和NATS等,并强调了服务拆分、通信机制、负载均衡等构建分布式系统的关键要素。通过选择合适的框架,遵循需求分析、技术选型、服务设计等步骤,开发者可以构建出高性能、高可用和可扩展的系统。此外,文中还提供了一个使用gRPC和etcd的简单代码案例来说明实现过程。
63 4
|
13天前
|
分布式计算 API 对象存储
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
Ray是一个开源的分布式计算框架,用于构建和扩展分布式应用。它提供了简单的API,使得开发者可以轻松地编写并行和分布式代码,而无需担心底层的复杂性。
|
15天前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
58 5
|
29天前
|
数据采集 JavaScript Java
一款分布式爬虫管理平台,支持多种语言和框架
项目介绍 Crawlab —— 一个基于 Golang 的分布式爬虫管理平台,支持Python、NodeJS、Go、Java、PHP 等多种编程语言以及多种爬虫框架。 主要功能:
|
1月前
|
Shell 虚拟化
分布式系统详解--框架(Zookeeper-基本shell命令)
分布式系统详解--框架(Zookeeper-基本shell命令)
26 1
|
1月前
|
XML 分布式计算 Hadoop
分布式系统详解--框架(Hadoop-单机版搭建)
分布式系统详解--框架(Hadoop-单机版搭建)
42 0
分布式系统详解--框架(Hadoop-单机版搭建)
|
16天前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
24 0
|
16天前
|
设计模式 安全 NoSQL
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
20 0
|
1月前
|
分布式计算 负载均衡 并行计算
Python 分布式计算框架 PP (Parallel Python):集群模式下的实践探索
该文介绍了使用Parallel Python (PP) 在两台物理机上构建分布式计算集群的经验。PP是一个轻量级框架,旨在简化Python代码在多处理器系统和集群中的并行执行。文中通过设置子节点的IP、端口和密钥启动PP服务器,并在主节点创建PP实例进行负载均衡。实验使用官方的质数和计算示例,显示PP在集群模式下能有效利用多台机器的多核CPU,实现计算效率的显著提升。未来,作者计划进一步研究PP在更复杂任务和大规模集群中的应用潜力。
158 4