您的位置:首页 > 其它

实现统计在线用户的几种方式

2013-07-12 10:43 211 查看
(转)

最近在考虑做个统计在线用户的功能。以前也做过,用的一些比较简单的方法,但是缺点也很明显:精确统计和服务器、数据库压力之间要做出平衡。

所以想找一个既能精确统计又能不占用太多服务器资源的方法。先说说一些平常的做法:

一,每次用户操作更新其在线时间

这个方法很直接,在用户表里加一个字段update_time,每次用户进行操作,都更新这个字段为当前时间,一般是在一个被所有Action继承的基类里写这个操作。

然后定义一个过期时间,比如10分钟,表示10分钟没进行任何操作的用户默认为不在线。这样,统计当前在线用户的sql语句大概是这样

select count(*) from think_user where update_time>now()-10*60

优点:实现简单,通俗易懂

缺点:1,对“在线”的定义模糊,万一用户看一篇文章时间比较长,10分钟内没进行任何操作,他就被忽略了;2,如果user表数据量很大,那效率将极差

二,将在线用户单独放入一张表

对于方法一的改进。新建一张表think_inline,字段有user_id、update_time,每次用户操作时,先判断表里有没有该用户的记录,没有则新增,有就更新update_time。

并同时加上删除失效数据操作

delete from think_inline where update_time<now()-10*60

这样,统计在线就可以直接count这张表就行了。而且这表的数据量不会很大(至少要比用户表小的多)

优点:减少数据库压力

缺点:仍然对“在线”的定义不准确

三,用JS定时器

这个方法是综合了一和二。新建一张表think_inline,也是在基类中定义每次用户操作时更新时间,参考二的做法。

不同之处是,在每个html模板里,加上一个js定时器,setInterval('updateTime',
10*3600);每隔10分钟发送一次ajax请求,更新update_time字段。这样,即使用户在一个页面停留时间过长,也不会被误认为不在线
了。并且可以通过减少请求的间隔,来增加精确度,当然了,对服务器的压力就更大了。

优点:对在线的判断较为准确

缺点:仍然不能既精确又不增加服务器压力,必须在两者之间进行取舍。

四,使用TP的SessionDb驱动进行最优化设计

这也就是网上有人说的session存入数据库的方法,这种方法优点很多。目前,LZ就是用的这个。

具体做法是。。。有50个评论,我就公布,当然了,跟百度的那些复制粘贴的例子不一样,会有深入解析哦!

没多少人看啊,先写一些。

1,为什么要将session存入数据库?

session是存储在服务器的一组临时数据。一般情况下,我们在做用户登录时,会将用户
数据存入session。这样,在任何页面都可以方便调用,而且每个客户端会产生唯一的session_id,不会混肴。并且在关闭浏览器后,服务器会有
session回收机制,自动删除过期session。

这是session的优点:唯一性、方便调用、不会过多占用资源。但是也有缺点:在客户端是以cookie方式保存的,禁用cookie就没用了。

那么,服务器是如何存放session的呢?他是默认将session以文件的方式保存在硬盘上的。可是,对于我们码农来说,操作数据库要比读文件方便的多,并且可以对session数据进行各种操作。

而统计在线用户人数就是通过统计有多少条session记录来实现的。

2,如何把session存入数据库?

TP的SessionDb驱动就实现了这个功能。原理就是通过改写PHP默认的session操作来实现,核心函数session_set_save_handler(),有兴趣的可以研究一下。该驱动将session的增、读、取、和删都放入了数据库。

使用方法也很简单:1,建表,驱动的注释里的sql语句运行下就好

2,添加配置:

//Session配置

'SESSION_TYPE' => 'db', //数据库存储session

'SESSION_TABLE' => 'think_session', //存session的表

'SESSION_EXPIRE' => 600, //session过期时间

这样,只要我们在程序里使用了session()函数,数据库里就会有记录。

3,利用数据库session实现统计在线用户

1,统计在线总人数

$map = array('session_expire'=>array('gt',NOW_TIME));

$inline = D('Session')->where($map)->count();

2,统计游客(未登录)人数

$map = array('session_expire'=>array('gt',NOW_TIME),'session_data'=>array('eq',''));

$huiyuan = D('Session')->where($map)->count();

3,统计会员(已登录)人数

$map = array('session_expire'=>array('gt',NOW_TIME),'session_data'=>array('neq',''));

$huiyuan = D('Session')->where($map)->count();

4,判断一个用户是否在线。

在用户表里新增一个字段:session_id。

(1)在登录操作里,保存该用户的session_id,

$session_id = session_id();

D('User')->where(array('id'=>$user_id))->save('session_id'=>$session_id);

(2)检查session表里是否存在该session_id,未过期并且有值,

$map = array('session_id'=>$session_id,'session_expire'=>array('gt',NOW_TIME),'session_data'=>array('neq',''));

$res = D('Session')->where($map)->find();

if($res){dump('该用户在线。')}else{dump('该用户不在线。')}

码字太麻烦啦,先写这么多,后面总结该方法的几大优点以及注意事项。

最后,还有最终总结。。。。。。有人看就发!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: