標籤:
原書用 Python 與 Redis 進行互動,我用 PHP 來實現。
環境:LNMP(CentOS 6.6 + Nginx 1.8.0 + MySQL 5.6.23 + PHP 5.6.9)+ Redis 3.0.7 + phpredis 2.2.4
首先在 Linux 開啟 Redis 服務:
[[email protected] ~]# cd /usr/local/redis/[[email protected] redis]# ./bin/redis-server ./etc/redis.conf [[email protected] redis]# ps aux|grep redis
如果顯示:
root 2239 0.2 0.1 35556 1744 ? Ssl 12:08 0:00 ./bin/redis-server *:6379 root 2243 0.0 0.0 5976 724 pts/0 S+ 12:08 0:00 grep redis
說明 Redis 服務已經開啟,連接埠號碼 6379
redis.php
<?php// 一周的秒數$seconds = 7 * 86400;define(ONE_WEEK_IN_SECONDS, $seconds);// 每投一票文章加的分值define(VOTE_SCORE, 432);// 執行個體化Redis對象$redis = new Redis();// 串連到Redis伺服器$conn = $redis->connect(‘localhost‘, 6379);
init_data.php 用於添加案例的資料
<?php/* 為投票網站準備資料 */require ‘redis.php‘;//1.根據發布時間排序文章的有序集合 zset$article_info = [‘100408‘=>[‘time‘=>strtotime(‘2016-4-10‘),‘score‘=>1332164063.49],‘100635‘=>[‘time‘=>strtotime(‘2016-4-28‘),‘score‘=>1332174713.47],‘100716‘=>[‘time‘=>strtotime(‘2016-4-29‘),‘score‘=>1332225027.26]];foreach($article_info as $key => $val) {$redis->zadd(‘time:‘, $val[‘time‘], ‘article:‘.$key);}//2.根據評分排序文章的有序集合 zsetforeach($article_info as $key => $val) {$redis->zadd(‘score:‘, $val[‘score‘], ‘article:‘.$key);}//3.為某篇文章(id:100408)投過票的使用者集合 set$users = [234487, 253378, 364680, 132097, 350917];foreach($users as $key => $val) {$redis->sadd(‘voted:100408‘, $val);}
vote.php 用於給文章投票,其中文章 id(article_id)和投票使用者 id(user_id)通過 get 方式傳遞(代碼清單 1-6 article_vote() 函數)
<?phpheader(‘Content-type:text/html;charset=utf-8‘);require ‘redis.php‘;$user_id = empty($_GET[‘user_id‘]) ? 0 : (int)$_GET[‘user_id‘];$article_id = empty($_GET[‘article_id‘]) ? 0 : (int)$_GET[‘article_id‘];function article_vote($redis, $user_id, $article_id) {$cutoff = time() - ONE_WEEK_IN_SECONDS;// 127.0.0.1:6379> zscore time article:100408// "1460217600"if(intval($redis->zscore(‘time:‘, ‘article:‘.$article_id)) < $cutoff) {return false;}if($redis->sadd(‘voted:‘.$article_id, $user_id)) {// ZINCRBY key increment member// 為有序集 score 的成員 article:100408 的 score 值加上增量 increment$score_new = $redis->zincrby(‘score:‘, VOTE_SCORE, ‘article:‘.$article_id);echo $score_new;// HINCRBY key field increment// 為雜湊表key中的域field的值加上增量increment。// 如果使用者是第一次為這篇文章投票,那麼增加這篇文章的投票數量和評分} else {return false;}return true;}if(! article_vote($redis, $user_id, $article_id)) {echo ‘投票失敗‘;} else {echo ‘投票成功‘;}
執行 http://yourdomain/init_data.php,完成 Redis 的串連和資料的初始化,可以進入 Redis 的用戶端查詢文章投票積分的有序集合(zset)和文章 100408 的投票使用者的集合(set):
[[email protected] redis]# ./bin/redis-cli127.0.0.1:6379> zrange score: 0 -1 withscores1) "article:100408"2) "1332164063.49"3) "article:100635"4) "1332174713.47"5) "article:100716"6) "1332225027.26"127.0.0.1:6379> zrange time: 0 -1 withscores1) "article:100408"2) "1460217600"3) "article:100635"4) "1461772800"5) "article:100716"6) "1461859200"
然後訪問 http://yourdomain/vote.php?user_id=100&article_id=100408 讓 user_id 為 100 的使用者給編號100408 的文章投票。
再次進入 Redis 的用戶端查詢文章投票積分的有序集合(zset)和文章 100408 的投票使用者的集合(set):
127.0.0.1:6379> zrange score: 0 -1 withscores1) "article:100408"2) "1332164495.49"3) "article:100635"4) "1332174713.47"5) "article:100716"6) "1332225027.26"127.0.0.1:6379> smembers voted:1004081) "100"2) "132097"3) "234487"4) "253378"5) "350917"6) "364680"127.0.0.1:6379>
發布文章 post_article.php(代碼清單 1-7 post_article() 函數)
<?phprequire ‘redis.php‘;// @param object $redis redis對象// @param int $user_id 使用者編號// @param string $title 文章標題// @param string $link 文章連結function post_article($redis, $user_id, $title, $link) {$article_id = $redis->incr(‘article:‘); // 產生新的文章id$voted = ‘voted:‘.$article_id;$redis->sadd($voted, $user_id); // 將發布文章的使用者添加到文章已投票的使用者名稱單中$redis->expire($voted, ONE_WEEK_IN_SECONDS); // 將投票名單的到期時間設定為一周$now = time();$article = ‘article:‘.$article_id;$redis->hmset($article, [‘title‘ => $title,‘link‘ => $link,‘poster‘ => $user_id,‘time‘ => $now,‘votes‘=> 1]); // 將文章的資訊儲存到一個散列裡$redis->zadd(‘score:‘, $now + VOTE_SCORE, $article); // 把文章添加到根據評分排序的有序集合中$redis->zadd(‘time:‘, $now, $article); // 把文章添加到根據發布時間排序的有序集合中return $article_id;}$user_id = isset($_GET[‘user_id‘]) ? $_GET[‘user_id‘] : 0;$mtid = mt_rand(0,999);$title = ‘文章標題‘.$mtid;$link = ‘http://www.youdomain.com/article/‘.$mtid;if(post_article($redis, $user_id, $title, $link)) {echo ‘success‘;} else {echo ‘error‘;}
訪問:http://yourdomain/post_article.php
由於 url 不帶參數並且 Redis 中不存在 article: ,因此會有一個 user_id 為 0 的使用者發布 article:1
此時查詢 Redis 中時間和分數的有序集合、article:1 的投票使用者集合以及 article:1 的散列內容:
127.0.0.1:6379> zrange time: 0 -1 withscores1) "article:100408"2) "1460217600"3) "article:100635"4) "1461772800"5) "article:100716"6) "1461859200"7) "article:1"8) "1465105632"127.0.0.1:6379> zrange score: 0 -1 withscores1) "article:100408"2) "1332164495.49"3) "article:100635"4) "1332174713.47"5) "article:100716"6) "1332225027.26"7) "article:1"8) "1465106064"127.0.0.1:6379> smembers voted:11) "0"127.0.0.1:6379> hgetall article:1 1) "title" 2) "\xe6\x96\x87\xe7\xab\xa0\xe6\xa0\x87\xe9\xa2\x9868" 3) "link" 4) "http://www.youdomain.com/article/68" 5) "poster" 6) "0" 7) "time" 8) "1465105632" 9) "votes"10) "1"
附:
文章案例來自《Redis 實戰》
Redis 命令參考:http://doc.redisfans.com/sorted_set/zrange.html
php-redis 中文文檔:http://www.cnblogs.com/weafer/archive/2011/09/21/2184059.html
《Redis in Action》筆記(一)文章投票(1)初始化資料 + 投票 + 發布文章