Redis优化建议(redis优化配置)
mhr18 2024-11-13 11:13 28 浏览 0 评论
优化的一些建议
1、尽量使用短的 key
当然在精简的同时,不要忘了 key 的 “见名知意”。对于 value 有些也可精简,比如性别使用 0、1。
2、避免使用 keys *
keys *, 这个命令是阻塞的,即操作执行期间,其它任何命令在你的实例中都无法执行。当 redis 中 key 数据量小时到无所谓,数据量大就很糟糕了。所以我们应该避免去使用这个命令。可以去使用 SCAN, 来代替。
3、在存到 Redis 之前先把你的数据压缩下
redis 为每种数据类型都提供了两种内部编码方式,在不同的情况下 redis 会自动调整合适的编码方式。
4、设置 key 有效期
我们应该尽可能的利用 key 有效期。比如一些临时数据(短信校验码),过了有效期 Redis 就会自动为你清除!
5、选择回收策略 (maxmemory-policy)
当 Redis 的实例空间被填满了之后,将会尝试回收一部分 key。根据你的使用方式,强烈建议使用 volatile-lru(默认) 策略 —— 前提是你对 key 已经设置了超时。但如果你运行的是一些类似于 cache 的东西,并且没有对 key 设置超时机制,可以考虑使用 allkeys-lru 回收机制,具体讲解查看 。maxmemory-samples 3 是说每次进行淘汰的时候 会随机抽取 3 个 key 从里面淘汰最不经常使用的(默认选项)
maxmemory-policy 六种方式 :
- volatile-lru:只对设置了过期时间的 key 进行 LRU(默认值)
- allkeys-lru : 是从所有 key 里 删除 不经常使用的 key
- volatile-random:随机删除即将过期 key
- allkeys-random:随机删除
- volatile-ttl : 删除即将过期的
- noeviction : 永不过期,返回错误
6、使用 bit 位级别操作和 byte 字节级别操作来减少不必要的内存使用。
- bit 位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
- byte 字节级别操作:GETRANGE and SETRANGE
7、尽可能地使用 hashes 哈希存储。
8、当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能。
9、想要一次添加多条数据的时候可以使用管道。
10、限制 redis 的内存大小(64 位系统不限制内存,32 位系统默认最多使用 3GB 内存)
数据量不可预估,并且内存也有限的话,尽量限制下 redis 使用的内存大小,这样可以避免 redis 使用 swap 分区或者出现 OOM 错误。(使用 swap 分区,性能较低,如果限制了内存,当到达指定内存之后就不能添加数据了,否则会报 OOM 错误。可以设置 maxmemory-policy,内存不足时删除数据。)
11、SLOWLOG [get/reset/len]
- slowlog-log-slower-than 它决定要对执行时间大于多少微秒 (microsecond,1 秒 = 1,000,000 微秒) 的命令进行记录。
- slowlog-max-len 它决定 slowlog 最多能保存多少条日志,当发现 redis 性能下降的时候可以查看下是哪些命令导致的。
优化实例分析
管道性能测试
redis 的管道功能在命令行中没有,但是 redis 是支持管道的,在 java 的客户端 (jedis) 中是可以使用的:
示例代码
// 注:具体耗时,和自身电脑有关 (博主是在虚拟机中运行的数据)
/**
* 不使用管道初始化 1W 条数据
* 耗时:3079 毫秒
* @throws Exception
*/
@Test
public void NOTUsePipeline () throws Exception {
Jedis jedis = JedisUtil.getJedis ();
long start_time = System.currentTimeMillis ();
for (int i = 0; i < 10000; i++) {
jedis.set ("aa_"+i, i+"");
}
System.out.println (System.currentTimeMillis ()-start_time);
}
/**
* 使用管道初始化 1W 条数据
* 耗时:255 毫秒
* @throws Exception
*/
@Test
public void usePipeline () throws Exception {
Jedis jedis = JedisUtil.getJedis ();
long start_time = System.currentTimeMillis ();
Pipeline pipelined = jedis.pipelined ();
for (int i = 0; i < 10000; i++) {
pipelined.set ("cc_"+i, i+"");
}
pipelined.sync ();// 执行管道中的命令
System.out.println (System.currentTimeMillis ()-start_time);
}
hash 的应用
示例:我们要存储一个用户信息对象数据,包含以下信息: key 为用户 ID,value 为用户对象(姓名,年龄,生日等)如果用普通的 key/value 结构来存储,主要有以下 2 种存储方式:
- 将用户 ID 作为查找 key, 把其他信息封装成一个对象以序列化的方式存储 缺点:增加了序列化 / 反序列化的开销,引入复杂适应系统(Complex adaptive system,简称 CAS)修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护。
- 用户信息对象有多少成员就存成多少个 key-value 对 虽然省去了序列化开销和并发问题,但是用户 ID 为重复存储。
- Redis 提供的 Hash 很好的解决了这个问题,提供了直接存取这个 Map 成员的接口。Key 仍然是用户 ID, value 是一个 Map,这个 Map 的 key 是成员的属性名,value 是属性值。( 内部实现:Redis Hashd 的 Value 内部有 2 种不同实现,Hash 的成员比较少时 Redis 为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的 HashMap 结构,对应的 value redisObject 的 encoding 为 zipmap, 当成员数量增大时会自动转成真正的 HashMap, 此时 encoding 为 ht )。
Instagram 内存优化
Instagram 可能大家都已熟悉,当前火热的拍照 App,月活跃用户 3 亿。四年前 Instagram 所存图片 3 亿多时需要解决一个问题:想知道每一张照片的作者是谁(通过图片 ID 反查用户 UID),并且要求查询速度要相当的快,如果把它放到内存中使用 String 结构做 key-value:
HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
"939"
测试:1 百万数据会用掉 70MB 内存,3 亿张照片就会用掉 21GB 的内存。当时 (四年前) 最好是一台 EC2 的 high-memory 机型就能存储(17GB 或者 34GB 的,68GB 的太浪费了), 想把它放到 16G 机型中还是不行的。
Instagram 的开发者向 Redis 的开发者之一 Pieter Noordhuis 询问优化方案,得到的回复是使用 Hash 结构。具体的做法就是将数据分段,每一段使用一个 Hash 结构存储.
由于 Hash 结构会在单个 Hash 元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在上面的 String 结构里是不存在的。而这个一定数量是由配置文件中的 hash-zipmap-max-entries 参数来控制的。经过实验,将 hash-zipmap-max-entries 设置为 1000 时,性能比较好,超过 1000 后 HSET 命令就会导致 CPU 消耗变得非常大。
HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
"939"
测试:1 百万消耗 16MB 的内存。总内存使用也降到了 5GB。当然我们还可以优化,去掉 mediabucket:key 长度减少了 12 个字节。
HSET "1155" "315" "939"
HGET "1155" "315"
"939"
启动时 WARNING 优化
在我们启动 redis 时,默认会出现如下三个警告:
- 一、修改 linux 中 TCP 监听的最大容纳数量
WARNING: The TCP backlog setting of 511 cannot be enforced because
/proc/sys/net/core/somaxconn is set to the lower value of 128.
在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。注意 Linux 内核默默地将这个值减小到 /proc/sys/net/core/somaxconn 的值,所以需要确认增大 somaxconn 和 tcp_max_syn_backlog 两个值来达到想要的效果。
echo 511 > /proc/sys/net/core/somaxconn
注意:这个参数并不是限制 redis 的最大链接数。如果想限制 redis 的最大连接数需要修改 maxclients,默认最大连接数为 10000
- 二、修改 linux 内核内存分配策略
错误日志:WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.
To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or
run the command'sysctl vm.overcommit_memory=1'
原因: redis 在备份数据的时候,会 fork 出一个子进程,理论上 child 进程所占用的内存和 parent 是一样的,比如 parent 占用的内存为 8G,这个时候也要同样分配 8G 的内存给 child, 如果内存无法负担,往往会造成 redis 服务器的 down 机或者 IO 负载过高,效率下降。所以内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)。
内存分配策略有三种
可选值:0、1、2。
- 0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
- 1, 不管需要多少内存,都允许申请。
- 2, 只允许分配物理内存和交换内存的大小 (交换内存一般是物理内存的一半)。
- 三、关闭 Transparent Huge Pages (THP)
THP 会造成内存锁影响 redis 性能,建议关闭
Transparent HugePages :用来提高内存管理的性能
Transparent Huge Pages 在 32 位的 RHEL 6 中是不支持的
执行命令 echo never > /sys/kernel/mm/transparent_hugepage/enabled
把这条命令添加到这个文件中 /etc/rc.local
相关推荐
- 一文读懂Prometheus架构监控(prometheus监控哪些指标)
-
介绍Prometheus是一个系统监控和警报工具包。它是用Go编写的,由Soundcloud构建,并于2016年作为继Kubernetes之后的第二个托管项目加入云原生计算基金会(C...
- Spring Boot 3.x 新特性详解:从基础到高级实战
-
1.SpringBoot3.x简介与核心特性1.1SpringBoot3.x新特性概览SpringBoot3.x是建立在SpringFramework6.0基础上的重大版...
- 「技术分享」猪八戒基于Quartz分布式调度平台实践
-
点击原文:【技术分享】猪八戒基于Quartz分布式调度平台实践点击关注“八戒技术团队”,阅读更多技术干货1.背景介绍1.1业务场景调度任务是我们日常开发中非常经典的一个场景,我们时常会需要用到一些不...
- 14. 常用框架与工具(使用的框架)
-
本章深入解析Go生态中的核心开发框架与工具链,结合性能调优与工程化实践,提供高效开发方案。14.1Web框架(Gin,Echo)14.1.1Gin高性能实践//中间件链优化router:=...
- SpringBoot整合MyBatis-Plus:从入门到精通
-
一、MyBatis-Plus基础介绍1.1MyBatis-Plus核心概念MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提...
- Seata源码—5.全局事务的创建与返回处理
-
大纲1.Seata开启分布式事务的流程总结2.Seata生成全局事务ID的雪花算法源码3.生成xid以及对全局事务会话进行持久化的源码4.全局事务会话数据持久化的实现源码5.SeataServer创...
- Java开发200+个学习知识路线-史上最全(框架篇)
-
1.Spring框架深入SpringIOC容器:BeanFactory与ApplicationContextBean生命周期:实例化、属性填充、初始化、销毁依赖注入方式:构造器注入、Setter注...
- OpenResty 入门指南:从基础到动态路由实战
-
一、引言1.1OpenResty简介OpenResty是一款基于Nginx的高性能Web平台,通过集成Lua脚本和丰富的模块,将Nginx从静态反向代理转变为可动态编程的应用平台...
- 你还在为 Spring Boot3 分布式锁实现发愁?一文教你轻松搞定!
-
作为互联网大厂后端开发人员,在项目开发过程中,你有没有遇到过这样的问题:多个服务实例同时访问共享资源,导致数据不一致、业务逻辑混乱?没错,这就是分布式环境下常见的并发问题,而分布式锁就是解决这类问题的...
- 近2万字详解JAVA NIO2文件操作,过瘾
-
原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。从classpath中读取过文件的人,都知道需要写一些读取流的方法,很是繁琐。最近使用IDEA在打出.这个符号的时候,一行代...
- 学习MVC之租房网站(十二)-缓存和静态页面
-
在上一篇<学习MVC之租房网站(十一)-定时任务和云存储>学习了Quartz的使用、发邮件,并将通过UEditor上传的图片保存到云存储。在项目的最后,再学习优化网站性能的一些技术:缓存和...
- Linux系统下运行c++程序(linux怎么运行c++文件)
-
引言为什么要在Linux下写程序?需要更多关于Linux下c++开发的资料请后台私信【架构】获取分享资料包括:C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdf...
- 2022正确的java学习顺序(文末送java福利)
-
对于刚学习java的人来说,可能最大的问题是不知道学习方向,每天学了什么第二天就忘了,而课堂的讲解也是很片面的。今天我结合我的学习路线为大家讲解下最基础的学习路线,真心希望能帮到迷茫的小伙伴。(有很多...
- 一个 3 年 Java 程序员 5 家大厂的面试总结(已拿Offer)
-
前言15年毕业到现在也近三年了,最近面试了阿里集团(菜鸟网络,蚂蚁金服),网易,滴滴,点我达,最终收到点我达,网易offer,蚂蚁金服二面挂掉,菜鸟网络一个月了还在流程中...最终有幸去了网易。但是要...
- 多商户商城系统开发全流程解析(多商户商城源码免费下载)
-
在数字化商业浪潮中,多商户商城系统成为众多企业拓展电商业务的关键选择。这类系统允许众多商家在同一平台销售商品,不仅丰富了商品种类,还为消费者带来更多样的购物体验。不过,开发一个多商户商城系统是个复杂的...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)