技术联盟

Redis使用问题一

Reid 使用指南一

问题一

OOM command not allowed when used memory > 'maxmemory'

这里表示使用内存超过了设置的最大内存。

redis.conf中的maxmemory定义REdis可用最大物理内存,有多种书写方式,以下均为合法:

maxmemory 1048576

maxmemory 1048576B

maxmemory 1000KB

maxmemory 100MB

maxmemory 1GB

maxmemory 1000K

maxmemory 100M

maxmemory 1G

没有带单位尾巴的为字节数,以B结尾的表示相应的大小。但需要注意KB和K、MB和M、GB和G是不同的,如1K表示1000字节,而1KB则为1024字节。如果maxmemory值为0,表示不做限制。

如果是32位系统,当maxmemory值为0时,redis启动时会记录WARN日志

Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.

server.maxmemory = 3072LL(10241024); /* 3 GB */

server.maxmemory_policy = MAXMEMORY_NO_EVICTION;

相关的源代码如下:

/* Convert a string representing an amount of memory into the number of

* bytes, so for instance memtoll("1Gb") will return 1073741824 that is

* (102410241024).

*

* On parsing error, if *err is not NULL, it's set to 1, otherwise it's

* set to 0. On error the function return value is 0, regardless of the

* fact 'err' is NULL or not. */

long long memtoll(const char *p, int *err) {

const char *u;

char buf[128];

long mul; /* unit multiplier */

long long val;

unsigned int digits;

if (err) *err = 0;

/* Search the first non digit character. */

u = p;

if (*u == '-') u++;

while(u && isdigit(u)) u++;

if (*u == '\0' || !strcasecmp(u,"b")) { // 调用strcasecmp不区分大小比较

​ mul = 1;

} else if (!strcasecmp(u,"k")) {

​ mul = 1000; // 不带尾巴B或b的

} else if (!strcasecmp(u,"kb")) {

​ mul = 1024; // 带尾巴B或b的

} else if (!strcasecmp(u,"m")) {

​ mul = 1000*1000; // 不带尾巴B或b的

} else if (!strcasecmp(u,"mb")) {

​ mul = 1024*1024; // 带尾巴B或b的

} else if (!strcasecmp(u,"g")) {

​ mul = 1000L10001000; // 不带尾巴B或b的

} else if (!strcasecmp(u,"gb")) {

​ mul = 1024L10241024; // 带尾巴B或b的

} else {

​ if (err) *err = 1;

​ return 0;

}

/* Copy the digits into a buffer, we'll use strtoll() to convert

* the digit (without the unit) into a number. */

digits = u-p;

if (digits >= sizeof(buf)) {

​ if (err) *err = 1;

​ return 0;

}

memcpy(buf,p,digits);

buf[digits] = '\0';

char *endptr;

errno = 0;

val = strtoll(buf,&endptr,10);

if ((val == 0 && errno == EINVAL) || *endptr != '\0') {

​ if (err) *err = 1;

​ return 0;

}

return val*mul;

}

如果要查看maxmemory的值,有如下三种方法:

  1. redis-cli -h ip地址 -p 6379 config get maxmemory

  2. redis-cli -h ip地址 -p 6379 info memory | grep maxmemory

    3.1. 登陆redis客户端:./redis-cli -h IP -p port -a passwd

    3.2. 执行命令:redis>info memory

若配置文件中,最大内存的策略设置为 maxmemory-policy volatile-lru 此配置只是清楚设置过期时间的key值,然而本应用并没有设置过期时间。

可以修改为maxmemory-policy allkeys-lru,指明非活跃近期很少用的key值清除。

如果清理完redis还不行,就需要考虑扩容

问题二

redis中java.io.IOException: 远程主机强迫关闭了一个现有的连接

现象:
登录系统后,隔一段时间后再操作出现java.io.IOException: 远程主机强迫关闭了一个现有的连接
原因:
redis服务器配置了timeout超时时间,spring serivice层中注入StringRedisTemplate,过了超时时间后该service对象持有的连接是无效的。
解决方案
1.配置redis连接池
spring.redis.lettuce.pool.max-idle: 30
spring.redis.lettuce.pool.min-idle: 10
spring.redis.lettuce.pool.max-active: 30
spring.redis.lettuce.pool.max-wait: 10000

  1. 检查tcp-keepalive配置 配置后重启redis tcp-keepalive配置为60

    在redis的配置文件redis.conf中设置tcp-keepalive时间为60s(据说3.2.1默认为300,我设置60后上述问题不在出现)

查看链接客户端

进入redis客户端执行 client list 查看

127.0.0.1:6379> CLIENT LIST

Share this:

码字很辛苦,转载请注明来自技术联盟《Redis使用问题一》

评论