原文来自:http://flask.pocoo.org/snippets/71/
功能需求:统计10分钟内在线用户数。
实现思路:利用Redis的Sets数据格式,以unix时间戳(秒)除以60的分钟数作为Redis的Key,value就是用户唯一标志(如id)的列表。当有新用户进来时,就将用户id加入当前这一分钟的队列里面去,并且将此key的超时设置为10分钟。
原文:
You can take the current time since 1970 in seconds, divide it by 60 and build a key based on that, then add a user to that set. Make the set expire after the maximum number of seconds you give a user in activity and when you want to query all active users you just build a union of the keys of the last N minutes.
主要代码:
from redis import Redis
redis = Redis()
import time
from datetime import datetime
ONLINE_LAST_MINUTES = 5
def mark_online(user_id):
now = int(time.time())
expires = now + (app.config['ONLINE_LAST_MINUTES'] * 60) + 10
all_users_key = 'online-users/%d' % (now // 60)
user_key = 'user-activity/%s' % user_id
p = redis.pipeline()
p.sadd(all_users_key, user_id)
p.set(user_key, now)
p.expireat(all_users_key, expires)
p.expireat(user_key, expires)
p.execute()
'''
根据用户最新活动时间,来判断该用户是否在线
'''
def get_user_last_activity(user_id):
last_active = redis.get('user-activity/%s' % user_id)
if last_active is None:
return None
return datetime.utcfromtimestamp(int(last_active))
'''
列出所有在线用户
'''
def get_online_users():
current = int(time.time()) // 60
minutes = xrange(app.config['ONLINE_LAST_MINUTES'])
return redis.sunion(['online-users/%d' % (current - x)
for x in minutes])
'''
将用户(标志为request.remote_addr)标记为在线状态
'''
@app.before_request
def mark_current_user_online():
mark_online(request.remote_addr)