|

使用 StackExchange.Redis 操作 redis 缓存,报错如下:
StackExchange.Redis.RedisServerException: 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.windows.conf 文件,需要重新启动 redis 服务,设置如下:
如果不想重启 redis 服务,可以通过 redis-cli 命令设置如下:
解释说明如下:
# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth. 简单地说:Redis在保存数据到硬盘时为了避免主进程假死,需要Fork一份主进程,然后在Fork进程内完成数据保存到硬盘的操作,如果主进程使用了4GB的内存,Fork子进程的时候需要额外的4GB,此时内存就不够了,Fork失败,进而数据保存硬盘也失败了。
查看 redis 日志,需要 redis.windows.conf 配置如下:
# Specify the log file name. Also 'stdout' can be used to force
# Redis to log on the standard output.
logfile "E:/Redis-x64-3.2.100/redis.txt"
日志异常如下:
[8984] 14 May 14:05:09.060 * Background saving started by pid 8672
[8672] 14 May 14:05:09.169 #
The Windows version of Redis reserves heap memory from the system paging file
for sharing with the forked process used for persistence operations.At this time there is insufficient contiguous free space available in the
system paging file. You may increase the size of the system paging file.
Sometimes a reboot will defragment the system paging file sufficiently for
this operation to complete successfully.
Redis can not continue. Exiting.
[8984] 14 May 14:05:09.278 # fork operation failed
经过分析,原来是最大堆大小“maxheap ”配置的问题,是因为可用的内存不足。
解决办法
打开Redis的配置文件“redis.windows.conf”,找到以下代码部分:
# The Redis heap must be larger than the value specified by the maxmemory
# flag, as the heap allocator has its own memory requirements and
# fragmentation of the heap is inevitable. If only the maxmemory flag is
# specified, maxheap will be set at 1.5*maxmemory. If the maxheap flag is
# specified along with maxmemory, the maxheap flag will be automatically
# increased if it is smaller than 1.5*maxmemory.
#
# maxheap <bytes>
增加此设置好,redis 服务无法启动!!!!!!!
默认的值是:maxheap 1024000000≈976.56M
我并没有在 conf 文件查找到此注释,我发现了如下注释:
# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# WARNING: not setting maxmemory will cause Redis to terminate with an
# out-of-memory exception if the heap limit is reached.
#
# NOTE: since Redis uses the system paging file to allocate the heap memory,
# the Working Set memory usage showed by the Windows Task Manager or by other
# tools such as ProcessExplorer will not always be accurate. For example, right
# after a background save of the RDB or the AOF files, the working set value
# may drop significantly. In order to check the correct amount of memory used
# by the redis-server to store the data, use the INFO client command. The INFO
# command shows only the memory used to store the redis data, not the extra
# memory used by the Windows process for its own requirements. Th3 extra amount
# of memory not reported by the INFO command can be calculated subtracting the
# Peak Working Set reported by the Windows Task Manager and the used_memory_peak
# reported by the INFO command.
#
# maxmemory <bytes>
警告:如果达到堆限制,不设置maxmemory将导致Redis终止并出现内存不足异常。
注意:由于Redis使用系统分页文件来分配堆内存,
Windows任务管理器或其他工具(如ProcessExplorer)显示的工作集内存使用情况并不总是准确的。简单来说,任务管理器显示的内存使用并不准确!!!
使用 info 命令查询如下:
# Memory
used_memory:2011338768
used_memory_human:1.87G
used_memory_rss:2011279992
used_memory_rss_human:1.87G
used_memory_peak:2011338768
used_memory_peak_human:1.87G
total_system_memory:0
total_system_memory_human:0B
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.00
mem_allocator:jemalloc-3.6.0
设置如下:
1073741824 bytes = 1G
设置后,redis .net 客户端新增缓存报错如下:
OOM command not allowed when used memory > 'maxmemory'. # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
# operations, when there are no suitable keys for eviction.
#
# At the date of writing these commands are: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction #MAXMEMORY策略:当MAXMEMORY
#到达。您可以从五种行为中选择:
#
#volatile lru->使用lru算法删除带有expire集的密钥
#allkeys lru->根据lru算法删除任何密钥
#volatile random->删除带有过期集的随机键
#allkeys random->删除随机键,任意键
#volatile ttl->删除过期时间最近的密钥(minor ttl)
#noeviction->完全不过期,只返回写操作错误
#
#注意:对于上述任何策略,Redis都会在写入时返回一个错误
#操作,当没有合适的键进行逐出时。
#
#在编写之日,这些命令是:set setnx setex append
#递增递减rpush lpushx lpushx linsert lset rpoplpush sadd
#烧结店sunion sunionstore sdiff sdiffstore zadd zincrby
#zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby酒店
#getset mset msetnx exec排序
#
#默认值为:
#
#maxmemory策略无效 还需要设置如下配置:
默认的redis设置是非常保守的,即内存超限后就不在存储,可以把策略修改为LRU算法(最近最少使用算法)——新存储的信息会替换掉旧的信息。
回顾:
(完)
|
上一篇:NPOI 单元格日期类型的判断下一篇:NPOI 操作 Excel 详解
|