在我的Django + postgresql网站上,我需要公开显示所有网站在某个时间点(这是一个社交网站)。 我该怎么做呢? 例如,是否有一种方法可以枚举在前10分钟内击中我的nginx web服务器的所有login用户? 像这样的东西可以工作。 我是一个初学者,现在正在寻找一个可行的解决scheme。
目前为了实现这一点,我将会话存储到数据库, 使用外部库来使会话可枚举。 这使我可以查询有多less唯一用户在某个时间点上线。
但是这个scheme造成了很多不必要的数据库stream量。 因此,日志和修剪日志变得无效。 此外pgFouine
告诉我会话相关的数据库调用是我的网站目前最大的性能瓶颈。
这里有一个build议的解决scheme,但它使用数据库。
使用Django的缓存框架来保存数据库查询的结果到内存。 这样您就不需要为每个页面渲染执行昂贵的数据库查询。
from django.core.cache import cache def count_current_users(): users = cache.get('users') if users is None: # last count has timed out users = do_expensive_db_query() cache.set('users', users, timeout=500) return users
https://docs.djangoproject.com/en/1.10/topics/cache/#basic-usage
您也可以使用模板片段缓存,并写入一个自定义模板标签,只有在缓存过期时才运行数据库查询。 这会将结果缓存500秒。
{% cache 500 logged_in_users %} {% expensive_query_db_for_logged_in_users %} {% endcache %}
如果你希望你的用户数量更实时,你可能必须绕过django的缓存框架,并直接与Redis通信。 将每个登录的用户作为密钥存储一段时间。 从Redis获取当前活动密钥的列表将比对sql数据库的等同查询便宜得多。 它也可以用几行python代码来实现。
如果您使用的是Django的用户会话, 会话模型有一个last_activity
字段。
您可能可以执行如下操作:
from user_sessions import Session from datetime import datetime, timedelta time_threshold = datetime.now() - timedelta(minutes=10) qs = Session.objects.filter(last_activity__gt=time_threshold)
虽然, django-user-sessions
没有在该领域的数据库索引,这意味着如果你有一个非常大量的用户/会话,该查询可能会很难,并需要很长的时间。 一个更复杂的答案可能涉及创建一个物化视图(如果您使用的是PostgreSQL),通过一个cron作业刷新。
目前,我正在尝试一种不同的方法。 我写了一个中间件,在每次请求时,用户的user_id
存储在一个全局排序的集合中。 我只在通过身份验证时才这样做,我使用redis键值存储来确保一切都非常快速。
解决方案还没有生效。 我会在这里报告更多,一旦完成就给出完整的答案。 在做出正确的解决方案之前,我还会考虑其他的答案。