[转帖]美团在Redis上踩过的一些坑-4.redis内存使用优化
(磁带已死,磁盘是新磁带,闪存是新磁盘,随机存储器局部性是为王道)
| userId(用户id) | weiboCount(微博数) |
| 1 | 2000 |
| 2 |
10 |
| 3 |
288 |
| .... | ... |
| 1000000 | 1000 |
| userId | hashKey | field |
| 1 | 0 | 1 |
| 2 | 0 |
2 |
| 3 | 0 |
3 |
| ... | .... | ... |
| 99 | 0 | 99 |
| 100 | 1 | 0 |
| 101 | 1 | 1 |
| .... | ... | ... |
| 9999 | 99 | 99 |
| 100000 | 1000 | 0 |
注意:
3. 获取方法:
- #获取userId=5003用户的微博数
- (1) get u:5003
- (2) hget allUser u:5003
- (3) hget u:50 f:3
4. 内存占用量对比(100万用户 userId u:1~u:1000000)
- #方法一 Memory
- used_memory:118002640
- used_memory_human:112.54M
- used_memory_rss:127504384
- used_memory_peak:118002640
- used_memory_peak_human:112.54M
- used_memory_lua:36864
- mem_fragmentation_ratio:1.08
- mem_allocator:jemalloc-3.6.0
- ---------------------------------------------------
- #方法二 Memory
- used_memory:134002968
- used_memory_human:127.80M
- used_memory_rss:144261120
- used_memory_peak:134002968
- used_memory_peak_human:127.80M
- used_memory_lua:36864
- mem_fragmentation_ratio:1.08
- mem_allocator:jemalloc-3.6.0
- --------------------------------------------------------
- #方法三 Memory
- used_memory:19249088
- used_memory_human:18.36M
- used_memory_rss:26558464
- used_memory_peak:134002968
- used_memory_peak_human:127.80M
- used_memory_lua:36864
- mem_fragmentation_ratio:1.38
- mem_allocator:jemalloc-3.6.0
那么为什么第三种能少那么多内存呢?之前有人说用了共享对象的原因,现在我将key,field,value全部都变成了字符串,仍然还是节约很多内存。
之前我也怀疑过是hashkey,field的字节数少造成的,但是我们下面通过一个实验看就清楚是为什么了。当我将hash-max-ziplist-entries设置为2并且重启后,所有的hashkey都变为了hashtable编码。
同时我们看到了内存从18.36M变为了122.30M,变化还是很大的。
- 127.0.0.1:8000> object encoding u:8417
- "ziplist"
- 127.0.0.1:8000> config set hash-max-ziplist-entries 2
- OK
- 127.0.0.1:8000> debug reload
- OK
- (1.08s)
- 127.0.0.1:8000> config get hash-max-ziplist-entries
- 1) "hash-max-ziplist-entries"
- 2) "2"
- 127.0.0.1:8000> info memory
- # Memory
- used_memory:128241008
- used_memory_human:122.30M
- used_memory_rss:137662464
- used_memory_peak:134002968
- used_memory_peak_human:127.80M
- used_memory_lua:36864
- mem_fragmentation_ratio:1.07
- mem_allocator:jemalloc-3.6.0
- 127.0.0.1:8000> object encoding u:8417
- "hashtable"
内存使用量:

- package com.carlosfu.redis;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Random;
- import org.junit.Test;
- import redis.clients.jedis.Jedis;
- /**
- * 一次string-hash优化
- *
- * @author carlosfu
- * @Date 2015-11-8
- * @Time 下午7:27:45
- */
- public class TestRedisMemoryOptimize {
- private final static int TOTAL_USER_COUNT = 1000000;
- private final static String HOST = "127.0.0.1";
- private final static int PORT = 6379;
- /**
- * 纯字符串
- */
- @Test
- public void testString() {
- int mBatchSize = 2000;
- Jedis jedis = null;
- try {
- jedis = new Jedis(HOST, PORT);
- List<String> kvsList = new ArrayList<String>(mBatchSize);
- for (int i = 1; i <= TOTAL_USER_COUNT; i++) {
- String key = "u:" + i;
- kvsList.add(key);
- String value = "v:" + i;
- kvsList.add(value);
- if (i % mBatchSize == 0) {
- System.out.println(i);
- jedis.mset(kvsList.toArray(new String[kvsList.size()]));
- kvsList = new ArrayList<String>(mBatchSize);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (jedis != null) {
- jedis.close();
- }
- }
- }
- /**
- * 纯hash
- */
- @Test
- public void testHash() {
- int mBatchSize = 2000;
- String hashKey = "allUser";
- Jedis jedis = null;
- try {
- jedis = new Jedis(HOST, PORT);
- Map<String, String> kvMap = new HashMap<String, String>();
- for (int i = 1; i <= TOTAL_USER_COUNT; i++) {
- String key = "u:" + i;
- String value = "v:" + i;
- kvMap.put(key, value);
- if (i % mBatchSize == 0) {
- System.out.println(i);
- jedis.hmset(hashKey, kvMap);
- kvMap = new HashMap<String, String>();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (jedis != null) {
- jedis.close();
- }
- }
- }
- /**
- * segment hash
- */
- @Test
- public void testSegmentHash() {
- int segment = 100;
- Jedis jedis = null;
- try {
- jedis = new Jedis(HOST, PORT);
- Map<String, String> kvMap = new HashMap<String, String>();
- for (int i = 1; i <= TOTAL_USER_COUNT; i++) {
- String key = "f:" + String.valueOf(i % segment);
- String value = "v:" + i;
- kvMap.put(key, value);
- if (i % segment == 0) {
- System.out.println(i);
- int hash = (i - 1) / segment;
- jedis.hmset("u:" + String.valueOf(hash), kvMap);
- kvMap = new HashMap<String, String>();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (jedis != null) {
- jedis.close();
- }
- }
- }
- }
| 方案 | 优点 | 缺点 |
| string |
直观、容易理解 |
|
| hash |
直观、容易理解、整合整体 |
|
| segment-hash |
内存占用量小,虽然理解不够直观,但是总体上是最优的。 |
理解不够直观。 |

[转帖]美团在Redis上踩过的一些坑-4.redis内存使用优化的更多相关文章
- [转帖]美团在Redis上踩过的一些坑-5.redis cluster遇到的一些问题
美团在Redis上踩过的一些坑-5.redis cluster遇到的一些问题 博客分类: redis 运维 redis clustercluster-node-timeoutfailover 转载请 ...
- [转帖]美团在Redis上踩过的一些坑-3.redis内存占用飙升
美团在Redis上踩过的一些坑-3.redis内存占用飙升 博客分类: 运维 redis redismonitor内存突增client listinfo 转载请注明出处哈:http://car ...
- 美团在Redis上踩过的一些坑-3.redis内存占用飙升(转载)
一.现象: redis-cluster某个分片内存飙升,明显比其他分片高很多,而且持续增长.并且主从的内存使用量并不一致. 二.分析可能原因: 1. redis-cluster的bu ...
- [转帖]美团在Redis上踩过的一些坑-2.bgrewriteaof问题
美团在Redis上踩过的一些坑-2.bgrewriteaof问题 博客分类: redis 运维 aofaof rewrite 转载请注明出处哈:http://carlosfu.iteye.com/b ...
- [转帖]美团在Redis上踩过的一些坑-1.客户端周期性出现connect timeout
美团在Redis上踩过的一些坑-1.客户端周期性出现connect timeout 博客分类: redis 运维 jedisconnect timeoutnosqltcp 转载请注明出处哈:http ...
- 美团在Redis上踩过的一些坑-目录(本人非美团)(转)
来自:http://carlosfu.iteye.com/blog/2254154 分为5个部分: 一.周期性出现connect timeout 二.redis bgrewriteaof问 ...
- Redis上踩过的一些坑
来自: http://blog.csdn.net//chenleixing/article/details/50530419 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DB ...
- redis主从复制踩到的那些坑
一.报错:* MASTER <-> SLAVE sync started # Error condition on socket for SYNC: No route to host解决: ...
- 【一个idea】YesSql,一种在经典nosql数据库redis上实现SQL引擎的方案(我就要开历史的倒车)
公众号链接 最高级的红酒,一定要掺上雪碧才好喝. 基于这样的品味,我设计出了一套在经典nosql数据库redis上实现SQL引擎的方法.既然redis号称nosql,而我偏要把SQL加到redis上, ...
随机推荐
- linux 搭建swoole
1安装依赖包yum -y install gcc gcc-c++ autoconf automake yum -y install zlib zlib-devel openssl openssl-de ...
- i春秋——“百度杯”CTF比赛 十月场——GetFlag(md5碰撞、文件包含、网站绝对路径)
需要提交的captcha满足等式,肯定就是MD5碰撞了 附上脚本 import hashlib def func(md5_val): for x in range(1,100000000): md5_ ...
- 浅谈华为验厂对MES系统的要求
众所周知,华为对供应商在管理.防错.品控.追溯等方面的要求都非常严格.在华为验厂时,对供应商的信息系统,尤其是MES系统的评估也是有非常具体的要求.那么我们今天就来谈谈华为验厂时,对MES系统有哪些具 ...
- android studio学习---模板
Android Studio还为开发人员提供多种模板选项,从而大大提升开发速度.这些模板能自动创建Activity以及必要的XML文件.大家还可以利用这些模板创建出较为基础的Android应用程序,并 ...
- 设计模式:单例(Sigleton)模式
题目:设计一个类,我们只能生成该类的一个实例. 只能生成一个实例的类是实现了Singleton(单例)模式的类型. 相关知识: 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象 ...
- 利用DNS日志进行MySQL盲注
0x01 技术原理 这里是利用load_file这个函数利用smb请求方式请求域名机器下的一个文件,由于计算机对该域名不熟悉所以需要优先请求DNS,所以我们通过DNS日志记录中的内容来获取回显.解决了 ...
- Linux下源码编译Mysql5.7
1.安装依赖包 yum -y install gcc-c++ ncurses-devel cmake make perl gcc autoconf automake zlib libxml libgc ...
- MySQL读写分离之MyCAT
Mycat实现MySQL主从复制读写分离 MyCAT的安装及部署 1.部署jdk环境 MyCAT用Java开发,需要有JAVA运行环境,mycat依赖jdk1.7的环境 1)上传jdk [root@l ...
- HAProxy的调度算法
HAProxy通过固定参数balance指明对后端服务器的调度算法,该参数可以配置在listen或backend选项中. HAProxy的调度算法分为静态和动态调度算法,但是有些算法可以根据参 ...
- LOJ 3119: 洛谷 P5400: 「CTS2019 | CTSC2019」随机立方体
题目传送门:LOJ #3119. 题意简述: 题目说的很清楚了. 题解: 记恰好有 \(i\) 个极大的数的方案数为 \(\mathrm{cnt}[i]\),则答案为 \(\displaystyle\ ...
