Redis各种数据类型的使用场景举例分析【一】

2018-04-20 10:00 By "Powerless" 3471 0 2

【一】字符串(String)

字符串的功能比较简单单一,容易理解的,类比一个数组的key-value。由于其数据结构的简单,所以也是来做简单的事,比如统计所有的小组数目,所有的相册数目,因为这些数据属于整个项目。

//用户创建相册的操作,以ThinkPHP的ORM为例
$data = array('name'=>'梦康的相册','create_id'=>'1','create_time'=>time());
$res = M('ablum')->add($data);
if($res){
	//全站相册总数加一
	$redis->incr('ablumCount');
}

那么某个用户的相册总数应该怎么存呢?

可以继续使用String来存储

$reids->set('user:1:ablumNum',1000)//设置id为1的用户的相册数为1000

上面的key的设计原则是:object-type:id:field,从对象的角度来分析,一个用户对象,name,ablumNum,groupNum等都是他的成员属性,如果是从数据的角度来分析,则是user表里面的id为1的用户的ablum_num字段的数据。

新增一个需求:如果需要取出相册总数前十的用户,怎么排序呢?

就应该考虑使用有序集合(sorted sets),这个后面说。


【二】哈希(Map)

hashMap的使用场景,hashMap特别适合用于存储对象。 相较于将对象的每个字段存成单个string类型,将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:

第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回。

第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识(id:name,id:age,id:birthday)来取得对应属性的值,虽然省去了序列化开销和并发问题,但是一个用户ID为重复存储了三次,如果存在大量这样的数据,内存浪费还是非常大的。


【三】列表(List)

redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。这使得list既可以用作栈,也可以用作队列。

产品运营总会让你展示最近、最热、点击率最高、活跃度最高等等条件的top list。注意list有做排行榜的功能,但是list却不方便在中间插入。如果某一个排行榜,确定是一小时跑一次,而不用中途又去人工干预,那么就可以使用list。如果需要后期人工干预排行榜,则最好是使用zsets的结构,可以后期插入。


【四】集合(sets)

集合使用的好处是快速往集合里插入一个元素,删除一个元素,确定一个元素是否存在于该集合。使用到的场景就是一个用户的粉丝,数据模型就是一对多的情况,一个用户可能有N个粉丝,所以就可以选择集合的数据结构。

$key = "user:$user:fans";
//$fansArr 是粉丝数组
foreach($fansArr as $fans){
	$redis->sAdd($key, $fans['id']);
}


【五】有序集合(zsets)

有序集合在项目中使用的最多,因为其比较方便做分页查询,比较容易控制顺序。比如我们项目中对搜索结果的数据就以zsets的结构来存的。因为方便排序。比如一个壁纸的关键字会有很多图片,以大家的点赞数来降序排列。

$key = "tagid:$id:search";
$redis->multi(Redis::PIPELINE);
foreach ($imagesArr as $image){
	//把点赞数作为权重,图片的id作为值
    $redis->zAdd($key, $image['fav_num'], $image['id']);
}
$redis->exec();

比如现在壁纸的搜索结果已经存在了,但是又有一位原创用户自己手绘的质量非常高的壁纸上传,这个时候,这个质量非常高的壁纸却没有阅读量,就没有点赞数,也不会存在于搜索列表的前面,所以需要人工干预下,给该图片增加一些权重,放入对应的缓存中,这样就实时更新了。


以上的这些情景基本涵盖了redis的一些比较有特色的使用情况吧。


评 论

View in WeChat

Others Discussion

  • PHP练习-移动数组内的0到最后并保持其他元素顺序不变
    Posted on 2020-08-14 20:32
  • PHP设计模式 - 委托模式
    Posted on 2019-04-25 16:15
  • HTTP头中隐藏PHP版本号
    Posted on 2021-01-11 16:38
  • Composer 异常 [ErrorException]
    Posted on 2019-11-25 17:55
  • PHP8.1 性能基准测试
    Posted on 2022-10-08 17:40
  • 必学十大经典排序算法,看这篇就够了
    Posted on 2019-11-18 16:30
  • Linux工具 - NM目标文件格式分析
    Posted on 2019-04-24 10:29
  • PHP练习-爬楼梯问题
    Posted on 2020-08-14 23:56