[转帖]美团在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上, ...
随机推荐
- 自回归(auto-regression)机制
在每个新单词产生后,该单词就被添加在之前生成的单词序列后面,这个序列会成为模型下一步的新输入.这种机制叫做自回归(auto-regression),同时也是令 RNN 模型效果拔群的重要思想. GPT ...
- cache verilog实现
cache原理: https://www.cnblogs.com/mikewolf2002/p/10984976.html cache的verilog实现 实现的cache是16k, 4way组相连c ...
- Linux CentOS 6.5 ifconfig查询不到ip简单解决方法
最近有小伙伴表示在虚拟机中安装CentOS之后使用ifconfig以及ip addr指令无法查询到ip地址, 在此笔者提供一个简单有效的方法; 1. 切换为root用户登录 su root 2.进入配 ...
- 使用aptitude安装软件
linux的版本依赖问题很令人纠结,不过我们可以通过使用aptitude软件包管理器来解决这个依赖问题,aptitude是可以选择合适的版本与匹配软件安装.
- PAT 乙级 1039.到底买不买 C++/Java
题目来源 小红想买些珠子做一串自己喜欢的珠串.卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖.于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么告诉她有多少 ...
- matplotlib---画等高线
contour - 绘制等高线 mp.contour(x, y, z, 等高线条数,colors=颜色, linewidth=线宽)#等高线绘制 contourf - 填充等高线 mp.contour ...
- generator 1(2019年牛客多校第五场B题+十进制矩阵快速幂)
目录 题目链接 思路 代码 题目链接 传送门 思路 十进制矩阵快速幂. 代码 #include <set> #include <map> #include <deque& ...
- django rest framework 序列化组件总结
序列化组件总结 一. 序列化组件本质上为了实现前后端分离,而进行json序列化的一个组件形式,极大方便了解析数据的作用 二. 所有序列化是基于APIView 解析器实现的,通过内部的多继承关系方便实现 ...
- windows server 2008 安装MySQL 8.0 遇到报错 1055 - Expression #1 of ORDER BY clause is not in GROUP BY
mysql安装参考教程:https://blog.csdn.net/qq_37350706/article/details/81707862 安装完毕后 执行sql语句 SELECT * FROM c ...
- 从架构开始谈dubbo(一)
架构发展史 一.单体应用架构 当网站流量很小时,所有的功能写在一个项目中,打包部署在tomcat中. 例如:公司管理系统,超市的收银系统 也可以将单体应用部 ...
