如果我在Flask应用程序中使用SimpleCache会出现什么问题

时间:2015-03-06 13:43:59

标签: python python-2.7 caching flask gunicorn

我们正在使用以下设置:NGINX + Gunicorn + Flask。我们需要添加一点缓存,每个Flask工作者不超过5Mb。 SimpleCache似乎是最简单的解决方案 - 它在Python进程本身内部使用内存。

不幸的是,文档说明了以下内容:

  

"单个进程环境的简单内存缓存。这个班   主要存在于开发服务器中,并且不是100%线程安全的。"

但是,在我们的设置中,我没有看到线程安全在哪里都很重要。我认为Gunicorn让几个Flask工作者在运行,每个工人都有自己的小缓存。什么可能出错?

2 个答案:

答案 0 :(得分:4)

我目前处理的情况是,在用户登录应用程序后,我想将他的IP,用户名插入数据库。

现在,我只能这样做的方法是使用Cache将用户的ip和用户名存储在缓存中。

现在每个gunicorn进程初始化自己的缓存时都会出现问题。如果为proc1' s缓存添加用户名+ ip组合,如果proc2接收到同一用户的下一个请求,它将无法在其缓存中找到它,因此将其再次添加到其缓存和数据库中,这是不合适。因此,在这种情况下,线程安全(进程安全)缓存很重要。

示例日志:

2015-07-07 22:42:31 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:31 - myapp.views:30 - DEBUG - from cache : user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:40 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:40 - myapp.views:30 - DEBUG - from cache : user1100.100.100.100, <type 'unicode'> [14776]
2015-07-07 22:42:41 - myapp.views:29 - DEBUG - not from cache user1100.100.100.100, <type 'unicode'> [14779]
2015-07-07 22:42:41 - myapp.views:30 - DEBUG - from cache : None, <type 'NoneType'> [14779]
2015-07-07 22:42:41 - myapp.views:32 - DEBUG - new username ip [14779]
2015-07-07 22:42:41 - myapp.views:38 - DEBUG - User : user1, ip : 100.100.100.100, noted at time : Tue Jul  7 22:42:41 2015, login_count : None [14779]

您可以看到gunicorn进程14776首先将其添加到其缓存中,并且下一个请求被14776选中,因此数据库条目只发生一次,但之后,下一个请求被14779选中,并将其添加到其缓存中因此db。

cache = SimpleCache(threshold=1000, default_timeout=3600)

使用基于memcache或redis的缓存可以解决它。我自己正在尝试。

答案 1 :(得分:1)

对于使用gunicorn的用例,没有多线程问题,因为每个服务在其自己的进程中单线程运行。但潜在的问题是“脏”读取数据。

考虑以下情况:

  1. process1从db读取并填充自己的缓存cache1
  2. process2使用相同的查询从同一个表中读取并填充自己的缓存cache2
  3. process2使用新数据更新表并使旧cache2无效
  4. process1再次执行相同的查询,使用过时的数据从cache1读取!这是因为process1 / cache1不知道数据库更新而出现问题