我现在用的方法是这样的:
用户表中有一个IsOnline和ActiveTime字段,用户登录后IsOnline属性就为true,然后客户端每隔3秒给服务器端发送一个心跳包,刷新ActiveTime字段为当前时间,服务器每隔30秒扫描一遍IsOnline属性为true的用户,发现最后收到的心跳包时间与当前时间之差大于10秒的(保守假设在通信线路上消耗的时间为2秒,那么正常情况下服务器是每5秒收到一个心跳包,10秒即连续收不到两个心跳包),那么,便将该用户的IsOnline属性置为false,表明该用户断线了。这样的问题是:
假如有3W个在线用户,那平均每秒就有1W个包发到服务端,而且会执行1W条update语句,这个开销太疯狂了,而且还会随着用户的增加等比例上升。大家做这种应用的时候是采用什么方法的呢?分享一下PS:好奇QQ是采用什么样的方式才判断用户在线状态的。。

解决方案 »

  1.   

    心跳包,和update语句有什么关系,难道你在不在线的标识还要写道数据库,这是你设计的缺陷
      

  2.   

    我觉得也不要一次心跳,就去Update一次数据库,在内存里查询要比较数据查询要好,只是你自己要定义一些规则来更新数据库的IsActive状态。关于QQ,听别个人说像是基于长连接的,具体也没有研究过:(
      

  3.   

    建议先用内存保存一段时间 在一起update到数据库
      

  4.   

    楼主,既然是C/s分布式的,就应该有应用程序服务,而且可以是N个服务,
    而不是client直接访问数据库,
    心跳包更新的是应用程序服务的在线用户信息,而不是数据库,
    如果用户太多,那么就不断地分割服务C/S中的S不是特指数据库服务器
      

  5.   

    一般判断客户端可以采用心跳包算法。在客户端发包到服务器。
    心跳包自己定义,一般包括用户的信息。比如说用户的ID(唯一标示用户的)
    然后在服务器中启动另外的线程接收客户端发过来的包。在统计数量。同时服务器也开始自己统计时间。
    判断当多少时间内没收到包。判断用户离线。
    具体技术:TCP编程。多线程编程。
      

  6.   


    1. 为什么要每隔3秒呢?为什么不是每隔15秒?2. 你的设计怎么跟数据库update扯上关系了呢?
      

  7.   


    实现心跳包一个比较好的方法是在服务器当接收到包后跟新一次数据库说明用户在线,然后通过程序中维护一张自定义表来判断用户离线。当离线判定成功在写一次数据库说明用户离线。
    具体实现可以全部在服务器。
    客户端首先发一个心跳包给服务器。
    服务器接收到包过后,在Update到数据库一次。说明用户在线。(比如置状态为0)
    然后服务器启动线程。每3S接收一次心跳包。统计每个用户心跳包个数。同时服务器在接收到客户端发送来的包时候自己也开始没3S计数。比较用户离线就判断服务器计数和客户端计数的相差多少就行了。
    这样就可以不用每一次去写数据库
      

  8.   

    to #5
    你误会了,我并没有让客户端直接连数据库,而是通过udp发包给服务器,服务器收到udp包后再更新数据库。我现在考虑的就是如果在内存中维护一个在线用户集合的话,然后我每隔30秒遍历一次这个集合,查看哪些用户已超过10秒没有心跳包发过来了,将他剔除这个集合。
    这样的话,比如这个集合有3W条记录,每30秒遍历一次,感觉就很吃性能。
    而且并发性也存在问题,比如在foreach遍历的时候,有另外的线程登录进来,就要将新用户加进集合中,这样遍历操作又会抛异常