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

「爱情、让人受尽委屈。」 2022-08-07 01:45 220阅读 0赞

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

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

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

Center

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

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

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

  1. 'components'=>array(
  2. //设置缓存
  3. 'cache'=>array(
  4. 'class'=>'CFileCache',
  5. ),
  6. ),

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

  1. A.缓存的赋值:
  2. Yii::app()->cache->set(key,value,过期时间,依赖条件);

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

  1. $products=['id'=>1,'name'=>'茅台酒'];
  2. Yii::app()->cache->set('product',
  3. $products,
  4. 30,
  5. newCGlobalStateCacheDependency('version')
  6. );
  7. 上面是一个常用的案例,我们将'product'作为key,$products数组当做value,过期时间为30秒(若永不过期此处填0),同时依赖全局缓存变量'version'这个值。

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

  1. B.缓存值的获取
  2. Yii::app()->cache->get(key);

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

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

读取线程代码:

  1. $products=Yii::app()->cache->get('product');
  2. //没有读取到缓存
  3. if($products===false)
  4. {
  5. $pro=Yii::app()->db;
  6. $products=$pro->createCommand("select*from{
  7. {product}}")->query();
  8. //设置缓存永不过期,同时依赖于全局变量'version'
  9. Yii::app()->cache->set('product',
  10. $products,
  11. 0,
  12. newCGlobalStateCacheDependency('version')
  13. );
  14. echo "从数据库获取<br/>";
  15. }
  16. echo json_encode($products);

写线程代码:

  1. $pro=Yii::app()->db;
  2. $command=$pro->createCommand("INSERTINTO{
  3. {product}}(`name`,`color`,`version`)VALUES('依赖','黑色',1)");
  4. $command->execute();
  5. //设置缓存依赖,让缓存过期
  6. $version=Yii::app()->getGlobalState('version');
  7. Yii::app()->setGlobalState('version',++$version);

上面的业务逻辑如下图:

Center 1

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

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

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

  1. 'components'=>array(
  2. //设置缓存
  3. 'cache'=>array(
  4. 'class'=>'CMemCache',
  5. 'servers'=>array(
  6. array('host'=>'192.168.1.16','port'=>11211,'weight'=>60),
  7. array('host'=>'192.168.1.16','port'=>11212,'weight'=>40),
  8. ),
  9. ),
  10. ),

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

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

Center 2

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

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

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

读线程代码:

  1. /**读线程
  2. *@return mixed
  3. */
  4. public function actionWide()
  5. {
  6. $products=$this->getCache();
  7. if(!$products)
  8. {
  9. $products=$this->getProducts();
  10. $this->setCache($products);
  11. echo "没有获取到缓存,从数据库读取数据。<br/>";
  12. }
  13. echo json_encode($products);
  14. }
  15. /**从缓存中读取数据
  16. *@return mixed
  17. */
  18. private function getCache()
  19. {
  20. return Yii::app()->cache->get('product');
  21. }
  22. /**从数据库读取数据
  23. *@return mixed
  24. */
  25. private function getProducts()
  26. {
  27. $pro=Yii::app()->db;
  28. $products=$pro->createCommand("select*from{
  29. {product}}")->query();
  30. $products=$products->readAll();
  31. return $products;
  32. }
  33. /**
  34. *更新缓存
  35. */
  36. private function setCache($products)
  37. {
  38. Yii::app()->cache->set('product',$products);
  39. }

写线程代码:

  1. /**
  2. *模拟写操作
  3. */
  4. public function actionWrite()
  5. {
  6. $pro=Yii::app()->db;
  7. $command=$pro->createCommand("INSERTINTO{
  8. {product}}(`name`,`color`,`version`)VALUES('依赖','黑色',1)");
  9. $command->execute();
  10. $this->delCache('product');
  11. echo "写成功";
  12. }
  13. /**根据键值删除缓存
  14. *@param$key键值
  15. */
  16. private function delCache($key)
  17. {
  18. Yii::app()->cache->delete($key);
  19. }

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

RedisCache

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

  1. 'components'=>array(
  2. //设置缓存
  3. 'cache'=>array(
  4. 'class'=>'ext.redis.CRedisCache',
  5. 'servers'=>array(
  6. array('host'=>'192.168.1.16','port'=>6379,),
  7. ),
  8. 'keyPrefix'=>'',
  9. ),
  10. ),

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

好了,就到这里了。

发表评论

表情:
评论列表 (有 0 条评论,220人围观)

还没有评论,来说两句吧...

相关阅读

    相关 分布式 分布式实现方案

    目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consi