Redis实战运用之HASH


声明:本文转载自https://my.oschina.net/u/3736695/blog/1581553,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

Redis实战运用之HASH

去年五月份的时候换了一个工作,到新公司要做一个娱乐新闻方面的项目,项目还挺大,主要涉及到的功能,包括各种数据排名、订阅、关注、点赞、评论、投piao、定向发布消息等。在和公司的另外一个技术讨论怎么做缓存的时候,了解redis这玩意,感觉还不错应用场景也非常适合,虽然我们两都没有用过redis,当即决定使用文件缓存和redis动静结合来做具体的缓存方案。

到现在项目上线一年多了,基于上面的缓存方案,至少现在网站每天稳定100W左右的流量,运行非常稳定。具体项目就不展示出来了。不过基于技术在于折腾的原则,最近用redis新折腾出来一个网站果图网(http://www.guotuw.com,各位可以访问了看下各个页面、各种功能测试等,速度还是过得去的。基本上前台所有的页面和功能基本都穿透不到数据库,全部数据都是实时的。 

好了废话基本说完了,下面具体说果图网(http://www.guotuw.com)各个功能点的具体实现:

redis安装配置,自己去谷歌。开发语言:PHP  框架:YII2 运行环境:LNMP 。

1、redis数据结构:HASH的运用

代码先上,用的是https://github.com/yiisoft/yii2-redis这个扩展封装了下面的方法,如果用PHP的reids扩展,各种方法能直接用不用封装。

class RedisService {          /***      * @desc 设置redis hash数据      * @param string $redisKey      * @param array $table      * @param int $expire 过期时间单位秒      * @return bool      */     public static  function setHash($redisKey = '',$table = [],$expire = 0 ){         if(empty($redisKey) || empty($table)) return false;          $params = [$redisKey];         foreach ($table as $key => $value){             if(!empty($value)){                 if(is_bool($value)){                     $value = (int)$value;                 }                 $params[] = $key;                 $params[] = $value;             }         }          if(count($params) > 1) Yii::$app->redis->executeCommand('HMSET',$params);     }       /**      * @desc 读取redis Hash数据      * @param string $redisKey      * @param array $fields      * @return array      */     public static function getHash($redisKey = '',$fields = []){         $data = $rs =  [];         if(empty($fields)){             $data = Yii::$app->redis->HGetall(trim($redisKey));              $count = count($data);             for($i = 0 ; $i < $count ; $i++){                 if($i % 2 != 0){                     $rs[$data[$i - 1]] = $data[$i];                 }             }         }else{             $fieldCount = count($fields);             for($i = 0 ; $i < $fieldCount ; $i++){                 $rs[$fields[$i]] = Yii::$app->redis->HGet($redisKey,$fields[$i]);             }         }          return $rs;     } }  RedisService::setHash('news:'.1000,['id' => 1000,'view' => 100000,'title' => '果图网上下了','content' =>'这是有很多美女的网站']; RedisService::getHash('news:'.1000,['id','title']); 

hash设置后的效果如图 ,范例存储的是具体的新闻数据 ,键:"new:新闻ID",其实哈希就是具体的单条记录,存储过后读取就会非常方便了。只需要ID(怎么来管理ID请往后看LIST相关)就能读取具体的数据了,由于redis是存储在基于内存的缓存,基于新闻这种数据的时效性,设置最多24个小时甚至更短的过期时间就能很快的释放内存,过期的新闻有命中的时候在设置一小段过期时间就可以了,长文本可以用PHP自带的函数压缩一下。

例如:http://www.guotuw.com网站的新闻、写真、明星数据都是放入HASH,访问对应的详情页面的时候根据ID确定HASH键值(news:ID)通过HGETALL或者HMGET命令从内存中读取数据肯定非常迅速啊,然后通过HINCRBY方法添加一个浏览量,是不是就完全避开数据库了。^_^

    /*      * 新闻详情页面 详情分页问题      */     public function actionInfo()     {         $id = (int)Yii::$app->request->get('id');                  $params['newInfo'] = News::getNewsInfoById($id);          if (empty($params['newInfo'])) $this->redirect('site/error');                  News::incrementView($id); //添加浏览量                 return $this->render('info', $params);     }      //News 里面的具体方法实现     public static function getNewsInfoById($newId = 0,$fields = []){         $newId = intval($newId);         if($newId < 1) return [];          empty($fields) && $fields = static::$fields;          $newInfo  = RedisService::getHash("news:".$newId,$fields);          if(empty($newInfo)){             $_newInfo = News::findOne($newId); //数据库读取数据             if($_newInfo){                 RedisService::setHash("news:".$newId,$_newInfo->attributes,,24 * 60 * 60);//缓存24小时                 $newInfo = ArrayHelper::filter($_newInfo->attributes,$fields); //获取指定字段             }         }          $newInfo && $newInfo = static::formatNewInfo($newInfo);//格式化新闻数据         return $newInfo;     }      //新闻添加访问量     public static function incrementView($newId,$increment = 1){         $newId = intval($newId);         if($newId > 0 && Yii::$app->get('redis')->exists('news:'.$newId)){                 Yii::$app->get('redis')->hIncrBy('news:'.$newId,'view',$increment);         }      } 

至于hash操作的其他命令,如下:

Hash(哈希表) 以下所谓的域其实相当于字段名名称:例如新闻的 title content view 
HDEL HDEL key field [field ...]

删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
 
HEXISTS HEXISTS key field

查看哈希表 key 中,给定域 field 是否存在。
HGET HGET key field

返回哈希表 key 中给定域 field 的值。
HGETALL HGETALL key

返回哈希表 key 中,所有的域和值。
HINCRBY HINCRBY key field increment

为哈希表 key 中的域 field 的值加上增量 increment 。增量也可以为负数,相当于对给定域进行减法操作。 例如:增加新闻的浏览量是不是很到位 HINCRBY news:100 view 1 
HINCRBYFLOAT HINCRBYFLOAT key field increment

为哈希表 key 中的域 field 加上浮点数增量 increment 
HKEYS HKEYS key

返回哈希表 key 中的所有域。
HLEN HLEN key

返回哈希表 key 中域的数量。
HMGET HMGET key field [field ...]

返回哈希表 key 中,一个或多个给定域的值。
HMSET HMSET key field value [field value ...]

同时将多个 field-value (域-值)对设置到哈希表 key 中。
HSET 设置单个域
HSETNX HSETNX key field value

将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。

若域 field 已经存在,该操作无效。
HVALS HVALS key

返回哈希表 key 中所有域的值。

基本上看方法名字就能知道其含义,更可况右边还给了具体的说明,有空自己去测试下,很快就能熟练运用了。

篇幅太长不好看的,分开讲先熟悉基本,后面写各种综合使用技巧。下一篇讲解LIST。

本文发表于2017年11月29日 16:33
(c)注:本文转载自https://my.oschina.net/u/3736695/blog/1581553,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2238 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1