首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >由于内存分配问题,redis无法在后台保存时对lua脚本的影响

由于内存分配问题,redis无法在后台保存时对lua脚本的影响
EN

Stack Overflow用户
提问于 2017-02-27 23:35:13
回答 1查看 397关注 0票数 0

最近,我向Django应用程序添加了一些Lua脚本(用于与Redis后端进行接口)。在生产中(虽然不是在开发中),设置最终会给出以下错误:

代码语言:javascript
复制
Error running script (call to f_8c07b227bc796743f66bad8dbe75a5bf8fcc8cd6): @user_script:2: @user_script: 2: -MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

当这种情况发生时,如果我查看redis日志,就会看到can't save in background: fork: Cannot allocate memory

我明白发生了什么。我的问题是,当内存不能分配给后台保存时,如何才能保持功能,但是lua脚本崩溃了吗?有没有办法避免这种情况?

下面是我的lua_scripts.py模块的布局方式:

代码语言:javascript
复制
import redis
from location import REDLOC2 #location of relevant unix socket

my_server = redis.StrictRedis(unix_socket_path=REDLOC2)

# Get recent
lualatestlogins = """
local l = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1]-600, '+inf') -- returns key:value pairs
local c = {}
for _, v in pairs(l) do
  local p = v:find(':')
  local i = v:sub(1,p-1)
  c[#c+1] = i
end
return c"""
getlatestlogins = my_server.register_script(lualatestlogins)

# Evict old
luacleanselogins = """
redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', '(' .. ARGV[1]-600)"""
cleanselogins = my_server.register_script(luacleanselogins)

# -- Store new
luastorelogin = """
redis.call('ZADD', KEYS[1], ARGV[1], ARGV[2] .. ':' .. ARGV[3])
redis.call('SET',KEYS[2],ARGV[3])
redis.call('EXPIRE',KEYS[2],600)"""
storelogin = my_server.register_script(luastorelogin)

# Retrieve collisions
luaretrieveclones = """
local q = redis.call('GET',KEYS[2]) 
if q == nil or q == '' then
  return nil               
else
  local l = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1]-600, '+inf')
  local c = {}
  for _, v in pairs(l) do  
    local p = v:find(':')  
    local i = v:sub(1,p-1) 
    local n = v:sub(p+1)   
    if n == q then         
      c[#c+1] = i          
    end
  end

  return c
end"""
retrieveclones = my_server.register_script(luaretrieveclones)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-28 02:27:14

错误消息告诉了您一切:可能修改数据集的命令被禁用.

Redis试图分叉一个新进程来进行后台保存,但由于内存不足而失败。在这种情况下,Redis将禁用数据库的任何更新。否则,内存中的数据和磁盘上的数据将不一致。

为什么当内存不能分配用于后台保存时,redis仍然保持功能

Redis仍然可以为只读请求提供服务,并拒绝任何可能修改数据库的请求。

但是lua脚本崩溃了?

lua脚本试图修改数据库,例如redis.call('ZADD', KEYS[1], ARGV[1], ARGV[2] .. ':' .. ARGV[3]),但是失败了。

有没有办法避免这种情况?

  1. 您应该监视这种错误,并将Redis移动到具有更多内存的新机器上,或者使用Redis集群进行扩展。
  2. 在lua脚本中,使用redis.pcall而不是redis.call。如果redis.call失败,整个脚本将终止。但是,如果redis.pcall失败,它将捕获错误并返回用于错误消息的lua表。您可以检查返回的表,以确定您的调用是否成功运行。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42497753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档