原书用 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 服务:
[root@localhost ~]# cd /usr/local/redis/ [root@localhost redis]# ./bin/redis-server ./etc/redis.conf [root@localhost 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.根据评分排序文章的有序集合 zset
foreach($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() 函数)
<?php
header(‘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):
[root@localhost redis]# ./bin/redis-cli 127.0.0.1:6379> zrange score: 0 -1 withscores 1) "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 withscores 1) "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 withscores 1) "article:100408" 2) "1332164495.49" 3) "article:100635" 4) "1332174713.47" 5) "article:100716" 6) "1332225027.26" 127.0.0.1:6379> smembers voted:100408 1) "100" 2) "132097" 3) "234487" 4) "253378" 5) "350917" 6) "364680" 127.0.0.1:6379>
发布文章 post_article.php(代码清单 1-7 post_article() 函数)
<?php
require ‘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 withscores 1) "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 withscores 1) "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:1 1) "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)初始化数据 + 投票 + 发布文章
原文:http://www.cnblogs.com/dee0912/p/5444780.html