您的位置:首页 > 数据库 > Redis

Redis实战运用之HASH

2017-11-29 00:00 609 查看

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
HDELHDEL key field [field ...]

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

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

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

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

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

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

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

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

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

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

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

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

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

篇幅太长不好看的,分开讲先熟悉基本,后面写各种综合使用技巧。下一篇Redis实战运用之LIST
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  php redis实战