4

我正在创建一个以 REST 为中心的应用程序,它将对大多数特定领域的模型使用某种 NoSQL 数据存储。对于我打算围绕 REST 数据框架构建的主站点,我仍然想为用户、计费信息和其他域数据模型范围之外的元数据使用传统的关系数据库。

我被告知,如果我可以尽可能避免对同一请求同时对 RDBMS 和 NoSQL 数据存储执行 I/O,则这种方法是一个好主意。

我的问题:

  1. 这是个好建议吗?(我假设是这样,但如果第一个前提是错误的,那么剩下的这些问题都是无用的。)
  2. 我想尽可能多地缓存至少登录的用户。是否可以使用 Django 会话以安全、可靠正确和容错的方式执行此操作?理想情况下,我希望会话 API 成为一个安全的、直接的替代品,以尽可能少地与用户表交互来检索当前用户。我需要做哪些跑腿工作才能把所有东西都连接起来?
  3. 如果这最终太麻烦,那么在不使用 django-nonrel 的情况下将用户信息存储在 NoSQL 存储中(即完全消除 RDBMS)有多容易?自定义身份验证/授权后端可以做到这一点吗?
4

1 回答 1

8

我正在考虑对我的应用程序使用相同的方法,我认为它通常是安全的,但需要特别注意解决缓存一致性问题。

Django 正常操作的方式是,当收到请求时,会针对 Session 表运行查询,以从请求中找到与 cookie 关联的会话。然后,当您访问时request.user,将对 User 表运行查询以查找给定会话的用户(如果有,因为 Django 支持匿名会话)。因此,默认情况下,Django 需要两个查询来将每个请求与一个用户相关联,这很昂贵。

Django session 的一个好处是它可以用作键值存储,而无需扩展任何模型类(与难以使用附加字段扩展的 User 类不同)。因此,您可以request.session['email'] = user.email在会话中存储其他数据。从某种意义上说,这是安全的,您从request.session字典中读取的内容肯定是您放在那里的内容,客户端无法更改这些值。因此,您确实可以使用这种技术来避免查询 User 表。

为避免查询 Session 表,您需要启用会话缓存(或使用 将会话数据存储在客户端 cookie 中django.contrib.sessions.backends.signed_cookies,这是安全的,因为此类 cookie 受到加密保护,不会被客户端修改)。

启用缓存后,您需要 0 个查询才能将请求与用户数据相关联。但问题是缓存一致性。如果您使用带有 write through 选项 ( django.core.cache.backends.locmem.LocMemCachewith django.contrib.sessions.backends.cached_db) 的本地内存缓存,则会话数据将在每次修改时写入 DB,但如果它存在于缓存中,则不会从 DB 中读取。如果您有多个 Django 进程,这会带来一个问题。如果一个进程修改了会话(例如更改session['email']),其他进程仍然可以使用旧的缓存值。

您可以通过使用共享缓存(Memcached 后端)来解决它,它保证一个进程所做的更改对所有其他进程都是可见的。通过这种方式,您将使用对 Memcached 后端的请求替换对 Session 表的查询,这应该更快。

在客户端 cookie 中存储会话数据也可以解决缓存一致性问题。如果您修改 cookie 中的电子邮件字段,则客户端发送的所有未来请求都应该有一个新的电子邮件。虽然客户端可以故意发送一个旧 cookie,它仍然带有旧值。这是否是一个问题取决于应用程序。

于 2013-01-20T12:22:51.127 回答