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

利用redis的list队列解决类似微博中msgbox表的性能问题

2012-12-11 14:26 537 查看
在常见的类似微博的社交应用中,用户发布一条新微博的时候需要把该微博信息写入follow他的用户的msgbox中。在用户活跃高峰期的时候,msgbox变成读写都很频繁的表(看微博的用户需要查询这个表的内容,写微博的用户同时需要往这个表写东西),同时这个表往往又是数据条数大表,在mysql中就很容易长时间锁表。我们采用redis来解决这个问题,redis主要两个功能:1)存储每个user最新的300条msgbox信息 2)作为队列存储待写入msgbox的msg列表

1.从msgbox中抽取对每个user抽取最新300条msgbox存在redis的sorted set中

利用phpredis的pipe批量写入

while (
$row = mysql_fetch_assoc ( $rs1 ) ) {

$score = convertStrToMillSecTime($row ['time']);

$userID = $row ['userID'];

$msgID = $row ['msgID'] ;

$pipe->zadd ( "ss-msgbox-$userID", $score, "$msgID,0" );

$pipe->zremrangebyrank ( "ss-msgbox-$userID", 0, -301 );

$sqlCount ++;

$totalcount ++;

if ($sqlCount >= 5000) {//5000条写入一次

$pipe->execute();

$sqlCount = 0;

$pipe = $redis->pipeline();

echo "current userID: $userID \n";

}

}

2.发微博的时候把微博写入微博表( msg)同时写入用户自己的msgbox,然后写入到redis的list,随后就返回前台。这样好处时发微博的人觉得很快,同时又能看到自己发的微博

写redis的list代码:

$obj = array
();

$obj ["senderID"] = $senderID;

$obj ["senderName"] = $senderName;

$obj ["content"] = $content;

$obj ["msgType"] = $msgType;

$obj ["attachment"] = $attachment;

$obj ["usericon"] = $usericon;

$obj ["resultMsgID"] = $resultMsgID;

$obj ["video"] = $video;

$obj ["notice"] = $notice;

$json_str = json_encode ( $obj );

$rs = $redis->lpush (
"msgbox-list", $json_str );

3.后台有个轮询的php程序来负责读取redis的list队列,然后解析后同时往mysql的msgbox和redis的sorted set中插入数据

轮询php代码:

while ( true ) {//循环

try
{

$str = $redis->brpop ( REDIS_MSGBOX_LIST, 20 );//block读,减小服务器负担

if ($str ==NULL) {

continue;

}

if (! mysql_ping ( $db )) {

mysql_close ( $db );

$db = mysql_connect ( DBHOST, DBUSER, DBPWD );

mysql_select_db ( DBNAME, $db );

}

if ($redis->ping () !="PONG") {//判断redis连接是否失效

// $redis->quit ();

$redis = new
Redis ();

$redis->connect ( REDIS_DB_HOST, REDIS_PORT );

$redis->auth ( REDIS_DB_PWD );

$redis->select ( REDIS_DB_NAME );

}

$obj = json_decode ( $str [1] );

_write_OtherInfo_exec($obj->senderID, $obj->senderName, $obj->content, $obj->msgType,
$obj->attachment, $obj->usericon, $obj->resultMsgID, $obj->video, $obj->notice);//写如msgbox表

} catch ( Exception $err ) {

$fp = fopen ( $log_file_path,
"w" );

fwrite ( $fp, getShanghaiCurrentTime () .
":" . $err->getMessage () );

flush ();

fclose ( $fp );

echo $err;

}

}

4.用户查询微博时,前300台直接从redis读id列表,然后从微博表读具体内容,超过300条再从msgbox表读取。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: