redis 大key(大约200M) 写入,为什么会内存暴涨?
发布于 6 年前 作者 JustforNode 4573 次浏览 来自 问答

如题,服务器是64G内存,16个cpu, redis有一个大约200M左右的有序集合,每次读取其中一个元素,然后更新它相对应的分值,在访问量稍稍大一点的时候,就会内存暴涨,实测会在几分钟之内redis内存占用会从几百兆飙到30多个G。 我的疑惑是,这个有序集合最大只有200M,所以不论怎样频繁的读写,都只是操作这200M的内存而已,为什么会占用那么高的内存呢?有大佬能给解惑一下吗?谢谢!

6 回复

会不会读取的代码有问题,比如一次读取过多,弄成了读取全部元素之类,这样redis打包数据比较消耗内存

把字符串 parse 成 JSON 对象内存耗费可不止 200M 哦

考虑异步了吗?

async function commonChangeDeviceId() {
	let setName = `vspOrderDevice.185.SortSet`;
	let realSdkVersion = 20;
	let deviceIdArray = await redisCli.zrangebyscore(setName,realSdkVersion,realSdkVersion);
	let changeDeviceId = _.sample(deviceIdArray);
	if (!changeDeviceId) {
    	deviceIdArray = await redisCli.zrangebyscore(setName,15,`(${realSdkVersion}`);
    	changeDeviceId = _.sample(deviceIdArray);
    	if (!changeDeviceId) {
        	deviceIdArray = await redisCli.zrangebyscore(setName,`(${realSdkVersion}`,28);
       		changeDeviceId = deviceIdArray[0];
    	}
	}
	if (changeDeviceId) { await redisCli.zincrby(setName,500,changeDeviceId); }
	return changeDeviceId || '';
}

代码是这样的@AnzerWall @hyj1991 @dingyuanwu, 代码大致意思是从有序集合优先随机取分值等于20的一个成员,如果没有,就随机取分值15-19之间的一个成员,如果还没有,就随机取21-28之间的一个成员,取到之后给该成员的分值加上500; 有序集合的单个成员模板是key: “352076091955843”,value:‘20’; 单个集合总共有200万成员,占200M内存,分值在15-28之间大约平均分配。 访问量稍微大一些,内存就爆了

@JustforNode 你一次zrange出来多少个数据量你统计过吗,感觉会很多,访问量多估计直接炸了。。

建议用一些比较取巧的手法,比如给score加上一些小数,然后随机一下选一个(limit 0 1)出来就行了(就以前那种sql经常干的事情,随机选一条数据,类似的手法),range一堆出来再随机选一个的做法很傻

@AnzerWall 应该就是一次range的数据太多了,导致内存爆了,(limit 0 1)是正解,没有注意到zrangebyscore的这个语法,感谢指导!!

回到顶部