Gettig RedisOutOfMemoryException



我正在使用Reddison为HashMap的键设置TTL

可以正常工作。但是,当插入大量数据时,比如在30分钟内插入500万数据,这些数据仍然保留在Redis中并且不会过期。AWS ElasticCache几次迭代后,数据库内存使用率达到100%

下面是我在sprint启动代码实现中使用的代码,并获得和异常

代码:

RMapCache<String, Object> map = getConnection().getMapCache(mapName);
map.put(key, obj, 15, TimeUnit.MINUTES);

异常:

org.redisson.client.RedisOutOfMemoryException: command not allowed when used memory > 'maxmemory'. script: 8002ee0f772fdaac4335bffe445fb53aef8dcd57, on @user_script:1.. channel: [id: 0x17227def, L:/10.224.59.44:59436 - R:10.224.57.111/10.224.57.111:6379] data: CommandData [promise=java.util.concurrent.CompletableFuture@120fc639[Not completed, 1 dependents], command=(EVAL), params=[local insertable = false; local v = redis.call('hget', KEYS[1], ARGV[5]); if v == false then insertable = true; else local t, val = struct.unpack('dLc0', v); local expireDate = 92233720368547758; local expireDateScore = redis.call('zscore', KEYS[2], ARGV[5]); if expireDateScore ~= false then expireDate = tonumber(expireDateScore) end; if t ~= 0 then local expireIdle = redis.call('zscore', KEYS[3], ARGV[5]); if expireIdle ~= false then expireDate = math.min(expireDate, tonumber(expireIdle)) end; end; if expireDate <= tonumber(ARGV[1]) then insertable = true; end; end; if tonumber(ARGV[2]) > 0 then redis.call('zadd', KEYS[2], ARGV[2], ARGV[5]); else redis.call('zrem', KEYS[2], ARGV[5]); end; if tonumber(ARGV[3]) > 0 then redis.call('zadd', KEYS[3], ARGV[3], ARGV[5]); else redis.call('zrem', KEYS[3], ARGV[5]); end; local maxSize = tonumber(redis.call('hget', KEYS[8], 'max-size')); if maxSize ~= nil and maxSize ~= 0 then     local currentTime = tonumber(ARGV[1]);     local lastAccessTimeSe..., 8, cid-phone-qa, redisson__timeout__set:{cid-phone-qa}, redisson__idle__set:{cid-phone-qa}, redisson_map_cache_created:{cid-phone-qa}, redisson_map_cache_updated:{cid-phone-qa}, redisson__map_cache__last_access__set:{cid-phone-qa}, redisson_map_cache_removed:{cid-phone-qa}, {cid-phone-qa}:redisson_options, ...], codec=org.redisson.codec.MarshallingCodec]
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:361) ~[redisson-3.18.1.jar!/:3.18.1]
at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:205) ~[redisson-3.18.1.jar!/:3.18.1]
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:144) ~[redisson-3.18.1.jar!/:3.18.1]
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:120) ~[redisson-3.18.1.jar!/:3.18.1]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501) ~[netty-codec-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366) ~[netty-codec-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) ~[netty-transport-4.1.52.Final.jar!/:4.1.52.Final]

这可能是如何使用Redison的问题。

你将500万份数据存储在Redis的一个散列中,然后试图根据字段过期。Redis在哈希中支持字段级过期。它可以使键过期,但不能使键中的元素过期,如Hash中的字段、Set中的成员或List中的项过期。

Redison以某种方式提供了这种功能。我对它不是很熟悉,但我知道它涉及到Lua脚本。我的猜测是Lua脚本没有机会运行,因为Redis接收数据的速度太快了。

然而,更重要的是,我认为在单个哈希中存储那么多数据并不是——至少一般来说——最好的解决方案。在一个地方有很多数据。包含该数据的键将存在于单个分片上,而不是分散在整个集群上,这会影响解决方案的水平可伸缩性。

你可能会更好地将每个值存储在一个字符串在Redis使用一个键名在Redis的mapName与你所称的key相结合。这将使用大量的键,这很好,因为它允许数据在集群中呈扇形分布。并且,它将允许Redis来处理过期而不是Redison。

希望这对你有帮助!

相关内容

  • 没有找到相关文章

最新更新