今天状态有点不佳,发生了点事情,让我深切的感受到,自身的无奈和痛苦。但也正因为如此,让我认识到自己的不足,也给我前进的动力和目标。曾子曰:“吾日三省吾身——为人谋而不忠乎?与朋友交而不信乎?传不习乎?”,曾子的确说的确对。^_^
好了废话差不多了,进入正题今天仔细、更用心一点,写好这篇博客。
3、redis数据结构:SET集合的运用
简单来说就像你把一袋土豆放到一个盆里,那么这个盆子,就可以说是一个集合。当然这个盆子里面的土豆,每一颗都是不一样的(不要跟我争^_^)。这个土豆呢,就可以说是集合的一个元素,redis里面这个元素就只是一个字符串。至此应该就大概已经明白了,把不重复的字符串,放在同一个容器中,而这个容器就是redis的集合。
既然明白了集合是什么,那么就能想到怎么来运用它,对此redis对于集合提供了很多的具体操作方法,例如:sadd添加元素,scard获取集合中元素数量、smembers获取所有元素、srandmember随机获取元素,srem删除元素,还有就是多个集合取交集、取并集,取差集等等。具体详细的操作方法我会贴在本文的最下边。
在来聊下集合的具体使用场景,例如我的果图网(www.guotuw.com)每个明星关联的写真现在其实不多,具体可以看一下这个页面http://www.guotuw.com/meinv/19298.html关联的写真这块,也不要求排序。
具体实现代码该贴上了:
$portrayIds = [1,3,5,2,34,2,32];//范例数据。 foreach ($portrayIds as $portrayId){ Yii::$app->get('redis')->sadd('starPortrays:'.$starId,$portrayId); } //这样我就把明星关联的写真数据设置好了 //明星详情页 public function actionInfo(){ $starId = (int)Yii::$app->request->get('id'); $starInfo = Star::getStarInfoById($starId); //这里的代码之前讲HASH的时候,贴过。 if(!$starInfo){ //TODO 404 } //添加浏览量 Star::incrView($starId);//同上贴过方法体 //相关写真 $portrays = Portray::getStarAllPortrays($starId,['id','title']); //看下面 return $this->render('info',[ 'star' => $starInfo, 'portrays' => $portrays, ]); } class Portray { //获取明星写真 public static function getStarAllPortrays($starId = 0,$fields=[]){ $starId = intval($starId); $portrayIds = Yii::$app->get('redis')->smembers('tagPortraySet:'.$starId); return static::formatPortrays($portrayIds,$fields); } //根据ID批量格式化写真数据。 //至于getPortrayById这个方法其实就是根据ID获取hash数据,前天专门写过一篇HASH的文章可以去看下哟。 public static function formatPortrays($portrayIds = [],$fields = []){ $rs = []; if($portrayIds){ empty($fields) && $fields = static::$fields; foreach ($portrayIds as $id){ $portrayInfo = static::getPortrayById($id,$fields); $portrayInfo && $rs[] = $portrayInfo; } } return $rs; } }
上面的代码中其实也只运用了sadd和smembers这两个方法,只是一个简单的范例。还有更多具体的方法操作自己可以多折腾下,
例如:我的果图网各个地方的随机推荐写真,随机推荐明星这些功能的时候,我就会用到srandmember这个功能,随机抽取count(srandmember参数)个元素出来,这种功能做起来就非常简单了。
再例如:我的果图网的写真美女大全页面,如果用集合来实现。如图:

假设用户想要查找:韩国美女 同时是 处女座 同时是 平面模特 同时是 甜美型 同时是 养眼 的美女,那么就只需要对这五个标签对应的美女数据去交集即可。这里就会用到sinter或者sinterstore函数,sinter是直接返回交集数据,而sinterstore会取交的结果节放到一个新的集合中去,直接用smembers读取新集合也能得到结果。就这么简单,这个页面的查询功能就搞定了,而且木有数据库查询。
sinterstore 其实这个函数把交集数据放到新集合其实就是做结果集的缓存啦,通过redis基本的expire或者expireat函数控制结果集的过期时间,释放内存。如果有用户请求相同的数据,也是这些查询条件,那么是不是就可以直接读取结果集了,还能避开redis去交集的运算,感觉挺爽,刺激。
如果你去我的果图网看了美女大全这个页面,看到了下图这一块:

这个页面的数据居然还能根据美女的浏览量排名,下面还有那么明显的一个分页。
那么问题就来了,如果用SET,数据根本就木有办法排序,也木有办法排序,怎么解?
此时此刻,SortedSet走到你面前昂首挺胸的对SET说,这些对我来说都是小case,一脸懵逼的SET立马怂回去依据:YOU CAN,YOU UP。
。。。。就这样。。。。SortedSet 闪亮登场。。。。。
预支后事如何,请听下回分解。下一篇讲SortedSet ,明天上。
本来是准备写在一起的,但是有事情来了。^_^
附上SET相关方法详细:
序号 | 命令及描述 |
1 | SADD key member1 [member2] 向集合添加一个或多个成员 |
2 | SCARD key 获取集合的成员数 |
3 | SDIFF key1 [key2] 返回给定所有集合的差集 |
4 | SDIFFSTORE destination key1 [key2] 返回给定所有集合的差集并存储在 destination 中 |
5 | SINTER key1 [key2] 返回给定所有集合的交集 |
6 | SINTERSTORE destination key1 [key2] 返回给定所有集合的交集并存储在 destination 中 |
7 | SISMEMBER key member 判断 member 元素是否是集合 key 的成员 |
8 | SMEMBERS key 返回集合中的所有成员 |
9 | SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合 |
10 | SPOP key 移除并返回集合中的一个随机元素 |
11 | SRANDMEMBER key [count] 返回集合中一个或多个随机数 |
12 | SREM key member1 [member2] 移除集合中一个或多个成员 |
13 | SUNION key1 [key2] 返回所有给定集合的并集 |
14 | SUNIONSTORE destination key1 [key2] 所有给定集合的并集存储在 destination 集合中 |
15 | SSCAN key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素 |