使用redis做pv、uv、click统计
2015-05-29 00:00
537 查看
redis实时统计
设计思路:
1、 前端smarty插件(smarty_function_murl),将网站所有的连接生成一个urlid,后端根据获取的参数将需要的数据存入redis。
2、后端插件(smarty_function_aurl),将urlid传入redis获取数据。
3、定时将数据跑出来存入关系数据库,清除redis记录
缩减开支事业部没了,编入其它组织了,这个东西我就停工了,分享下思路和代码。
设计思路:
1、 前端smarty插件(smarty_function_murl),将网站所有的连接生成一个urlid,后端根据获取的参数将需要的数据存入redis。
2、后端插件(smarty_function_aurl),将urlid传入redis获取数据。
3、定时将数据跑出来存入关系数据库,清除redis记录
缩减开支事业部没了,编入其它组织了,这个东西我就停工了,分享下思路和代码。
<?php /** * 使用redis统计pv、uv、链接的点击数。每个链接都需要一个唯一的id,将这个id记录做点击数的key。类不能直接单独使用,只是提供了一个思路。为pv 500W做的测试。项目停了没有进下去,分享下思路。 * @author [email]pigletshake@gmail.com[/email] * @version * 策略部署两台redis主从结构,复制信息。每天程序抛出数据,5天清除一次。 */ namespace mokbuy\helper; class Analytics { //page view 的key; private $_pv_key = 'aitily::pv:::'; //用户唯一id 的可以; private $_uv_key = 'aitily::uv::'; //用户访问轨迹的key,hs=history private $_hs_key = 'aitily::hs::'; //点击记录 private $_ck_key = 'aitily::ck::'; //url key private $_url_key = 'aitily::urlid::'; //首页key public $_homepage_key = null; private $_redisr=null; private $_redisw=null; private $_key=null; private $_time=null; //构造函数 public function __construct() { //连接redis $this->_redisr = $this->redisr(3); $this->_homepage_key = md5("homepage"); $this->_time = $this->_time(); $this->_key = date('Ymd', $this->_time); } /** * 保存消息 * @param string $urid urlid * @param string $sid 用户id * @Return 参数不全-1,redis连接失败-2 */ public function s($urid=null,$sid=null) { if(isset($_GET['anys'])) return false; //todo,还需要监测urid和sid参数的准确性 $urlid = empty($urid)?(isset($_GET['urid'])?$_GET['urid']:md5('homepage')):$urid; $sid = empty($sid)?(isset($_GET['sid'])?$_GET['sid']:session_id()):$urid; //连接redis $_redisw = $this->redisw(3); if (!$_redisw) return '-2'; //redis连接失败 //获取变量信息; $url_request = $urlid == $this->_homepage_key ? 'homepage' : $urlid; //echo $url_request; $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'direct'; //请求地址,第一次访问 $agen = $_SERVER['HTTP_USER_AGENT']; $time = $this->_time; $key = $this->_key; $ip = self::_ip(); //获取上一页的urlid $history_urlid = '0'; if ($url_request == 'homepage') { $history_urlid = md5('homepage'); } else { $history_url_arr = explode('&', $referer); if (count($history_url_arr) > 1) $history_urlid = str_replace('urid=', '', $history_url_arr[count($history_url_arr) - 1]); } //==开始统计== //统计按url id做key开始第一次统计,value:上一级页面为主;for:为了按urlid统计pv $_redisw->zadd($this->_url_key . $urlid, $time, $referer . '::' . $ip . '::' . $time . '::' . $sid); //点击数统计 // var_dump($history_urlid); if ($url_request != 'homepage')//如果第一次访问不会产生点击数 $_redisw->zadd($this->_ck_key . $history_urlid, $time, $referer . "::" . $url_request . '::' . $time . '::' . $sid); //每天的pv统计 $_redisw->zadd($this->_pv_key . $key, $time, $url_request . '::' . $agen . "::" . $time . '::' . $sid); //用户浏览历史 $_redisw->zadd($this->_hs_key . $key . '::' . $sid, $time, $url_request . '::' . $referer . '::' . $ip . '::' . $time); return true; } /** * 返回 redis 实例 * @staticvar \Redis $_redis * @param int $database redis数据库 * @return \Redis */ public function redisw($database = 2) { static $_redis_w; if (is_null($_redis_w) || !($_redis_w instanceof \Redis)) { $_redis_w = new \Redis; $_redis_w->pconnect("xx.xx.xx.xxx:8301"); $_redis_w->auth('abc'); } $_redis_w->select($database); return $_redis_w; } /** * 读 返回 redis 实例 * @staticvar \Redis $_redis * @param int $database redis数据库 * @return \Redis */ public function redisr($database = 2) { static $_redis_r; if (is_null($_redis_r) || !($_redis_r instanceof \Redis)) { $_redis_r = new \Redis; $_redis_w->pconnect("xx.xx.xx.xxx:8301"); $_redis_r->auth('abc'); } $_redis_r->select($database); return $_redis_r; } // 析构函数 public function __destruct() { } /** *按天查询pv总数 * @param string $day * 可以为空,默认是查询当天的(20121220) * @return int */ public function pv($day=null) { if(empty($day)) $day = $this->_key; $key=$this->_pv_key.$this->_key; return $this->_redisr->zcard($key); } /* * 按天查询uv * @param string $day * 可以为空,默认是查询当天的(格式=20121220) * @return int */ public function uv($day=null) { if(empty($day)) $day = $this->_key; $key=$this->_hs_key.$this->_key; return count($this->_redisr->keys($key."*")); } /* * 按条件查询pv,uv数据 * @param string $type,按类型查询,支持{pv、uv、ck} * @param string $key,查询的key目前支持{$urlid\},默认查询首页的key * @param int $start 开始时间,时间戳格式,默认当天凌晨 * @param init $end 结束时间戳,默认当前时间戳 * $return int */ public function pvslot($type='pv',$key=null,$start=0,$end=0) { $pv=$uv=0; $pv_arr=array(); if(empty($key)) $key = $this->_homepage_key; if($start==0) $start = strtotime (date('Ymd' . '00:00:01')); if($end==0) $end = $this->_time; //统计pv的数据 $pv_arr = $this->_redisr->zrangebyscore($this->_url_key.$key, $start, $end); $pv=count($pv_arr); if($type=='pv') return $pv; //统计uv的数据 $uv_arr = array(); if ($pv > 0) { //direct::10.2.5.186::1356073254::ju82lv4girj508udt0dv6bts72 foreach ($pv_arr as $po): $po_ar = explode('::', $po); if (!in_array($po_ar[3], $uv_arr)) { $uv_arr[] = $po_ar[3]; } endforeach; $uv = count($uv_arr); } unset($pv_arr); unset($uv_arr); if($type=='uv') return $uv; //统计ck点击数 if($type=='ck') return count($this->_redisr->zrangebyscore($this->_ck_key.$key,$start,$end)); //url pv } /* * ip地址 */ static function _ip() { foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR') as $p) { if (!empty($_SERVER[$p])) { return $_SERVER[$p]; } } } /** * 获取当前时间 * @return int */ public function _time() { !$this->_time && $this->_time = time(); return $this->_time; } } /* * pv思路 * ==按天统计== * r->zdd(天,时间戳,url:sid) ; * 统计今天的pv数:r->zcard(今天) return int; * 统计某天某个时间段的pv个数 r->zcount(天,时间戳开始,时间戳结束) return int; * 统计某个时间段的pv详细数据 r->zrangebyscore(天,开始时间戳,结束时间戳) return array;如果是月的需要另算>10天>mysql,统计 * ==按url统计pv== * $_redis->zadd(url,时间戳,$ip.'::'.$sid));//value值暂时没有想法 * 统计某个url的pv数:r->zcard(url) return int; * 统计某个url某个时间段的pv个数 r->zcount(url,时间戳开始,时间戳结束) return int; * 统计某个时间段的pv详细数据 r->zrangebyscore(url,开始时间戳,结束时间戳) return array;如果是月的需要另算>10天>mysql,统计 * ==策略== * 主库负责插入操作 * 从库1负责备份和查询。 * 从库1负责数据到mysql的工作。 * 从库2负责备 * * */ ?>
相关文章推荐
- jedis以pipeline方式调用redis
- redis常用配置
- redis超时
- redis运行分析
- Redis 命令参考――PubSub(发布订阅)
- redis应用场景
- redis系统学习--list
- redis系统学习-set
- redis系统学习-sorted-set
- redis系统学习-string命令
- redis系统学习-hashes
- redis系统学习--命令
- redis系统介绍
- redis组建介绍
- redis安装与参数说明
- jedis使用:redis常用元素的使用!
- 为啥 redis 使用跳表(skiplist)而不是使用 red-black?
- ycache中redis主备功能设计及使用说明
- win7 安装Redis
- redis cluster安装笔记