Redis 开发陷阱及避坑指南!

简介: Linux 配置优化我们在使用 Redis 过程中,可能更多的关注 Redis 本身的一些配置优化,如 AOF、RDB 配置、数据结构配置优化等。但是很少关心 Redis 的载体,服务器的优化。而这往往为我们的项目运行带来灾难性的打击。因此服务器优化也是必不可少的。

Linux 配置优化

我们在使用 Redis 过程中,可能更多的关注 Redis 本身的一些配置优化,如 AOF、RDB 配置、数据结构配置优化等。


但是很少关心 Redis 的载体,服务器的优化。而这往往为我们的项目运行带来灾难性的打击。因此服务器优化也是必不可少的。


内存分配控制

Redis 启动时,可能会出现下面的日志

# 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' for this to take effect.

overcommit 是 Linux 的一种内存处理机制:Linux 对绝大多数内存申请都会回复 yes,以便运行更多的程序。因为申请内存后,并不会马上使用内存。这种机制就是 overcommit 。


而 overcommit_memory 是用来设置内存分配策略的,有三种取值


image.png


日志中 Background save 指的是 bgsave 和 bgrewriteaof 。根据操作系统的配置,如果 overcommit_memory 设置为 0 则可能会造成内存申请失败而导致后台持久化失败。


因此 Redis 建议将这个值设置为 1 是为了 fork 操作在低内存下也能执行成功。


设置方法

通过命令修改,立即生效。重启后会失效

sysctl vm.overcommit_memory=1

再将改动写入系统配置文件,使其永久有效

echo "vm.overcommit_memory=1" >> /etc/sysctl.conf

建议

采用 Redis 建议的配置是为了在极端情况下 Linux 可以挤出来一些内存供 Redis 备份,但是更建议优先配置好 maxmemory ,给机器留 20%~30% 的空闲内存。


硬盘虚拟内存

swap 是指当物理内存不足时,拿出部分硬盘空间当 SWAP 分区(虚拟成内存)使用。我们都知道硬盘的读写速度相对于内存实在是太鸡肋,对于高并发、高吞吐的应用来说,磁盘IO通长会成为系统瓶颈。Linux 系统中 swappiness 的值控制操作系统使用 swap 的倾向程度。

查看内核版本:

uname -sr

image.png

动使用 SWAP


PS:OOM Killer 是指当 Linux 发现操作系统内存不足时,主动杀死一些非内核进程的操作


设置方法

echo {value} > /proc/sys/vm/swappiness


echo vm.swappiness={value} >> etc/sysctl.conf


监控swap

查看 Swap 的总体情况

free -m

image.png

最后一行即展示了 Swap 的使用情况,一共 2047 Mb,以使用 0 Mb,空闲 2047 Mb


实时查看 Swap 的使用

image.png


参数 si 表示 swap in ,so 表示 swap out 在我的机器上都是 0 表示没有使用交换


查看指定进程的 Swap 情况

通过 ps -ef |grep redis 查看 Redis 进程号,例如 1621


通过 cat /proc/1621/smaps | grep Swap 命令查看每个内存块 Redis Swap 的使用情况


THP 内存页大小

Redis 启动时可能会看到下面的日志

WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

提示告诉我们建议修改 Transparent Huge Pages (THP) 的配置,Linux kernel 在 2.6.38 内核增加了 THP 特性,支持大内存页(2MB)分配,默认开启。


开启后可加快 fork 子进程的速度,但是 fork 操作后,每个内存页从原来的 4KB 变为 2MB,会大幅加重重写期间父进程内存消耗。


同时每次写命令引起的复制内存页单位放大了512倍。会拖慢写操作的执行时间。造成大量的写操作慢查询因此 Redis日志中建议禁用它。另外关注Java技术栈公众号在后台回复面试可以获取一份面试题大全。

方法如下:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

另外在 /etc/rc.local 中追加

echo never > /sys/kernel/mm/transparent_hugepage/enabled

对于某些发行版本(例如红帽6以上)配置文件不在这个位置(在 /sys/kernel/mm/redhat_transparent_hugepage/enabled),但是 Redis 检查 THP 是写死的此位置,所以虽然这么修改后 Redis不报警然而实际是没有作用的,需要注意。应该改动对应位置的值


使用NTP 同步时间

在集群或哨兵环境中,多台服务器使用相同的网络时间协议同步时间能更方便的阅读日志,排查问题


可以设置定时任务同步时间

crontab -u //设定某个用户的cron服务
crontab -l //列出某个用户cron服务的详细内容
crontab -r //删除某个用户的cron服务
crontab -e //编辑某个用户的cron服务
crontab -i //打印提示,输入yes等确认信息

添加每小时执行一次的任务

0 * * * * /usr/sbin/ntpdate cn.pool.ntp.org > dev/null 2>&1

最大连接数限制

通过 ulimit -a 命令查看和设置当前用户进程的资源数,其中包含 open files 参数,是单个用户同时打开的最大文件描述符个数。虽然 Redis 中可以配置最大的客户端连接数(默认 10000) 。

Redis 内部最多使用 32 个文件描述符。当 open files = 4096 时,Redis 最大提供 4096-32=4064 个连接。因为它不能突破操作系统的限制。如果需要,使用如下命令修改:

ulimit -Sn {max-open-files}

TCP backlog

tcp backlog 配置的是 tcp 握手时候的队列大小。如果该值过小。会导致高并发场景下部分连接第三次握手ACK被丢弃。关于 backlog

The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

Redis启动时,会告诉我们系统配置中该值是 128,而 Redis 511。这个 511 是没用的,因为系统比这个小。需要修改系统 backlog 的值。

echo 511 > /proc/sys/net/core/somaxconn
相关文章
|
存储 缓存 NoSQL
在Python Web开发过程中:数据库与缓存,Redis在Web开发中的常见应用场景有哪些?
Redis在Python Web开发中常用于缓存、会话管理、分布式锁、排行榜、消息队列和实时分析。作为内存数据存储,它提供高效的数据结构(如字符串、哈希、列表、集合、有序集合),支持会话存储、互斥操作、计数与排名、队列实现及实时数据处理。其高速性能和丰富功能使其成为多场景下的理想选择。
274 5
|
9月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
843 79
|
NoSQL API Redis
最佳实践|如何使用c++开发redis module
本文将试着总结Tair用c++开发redis module中遇到的一些问题并沉淀为最佳实践,希望对redis module的使用者和开发者带来一些帮助(部分最佳实践也适用于c和其他语言)。
76962 0
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
338 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
NoSQL API Redis
c++开发redis module问题之为什么在使用RedisModule_GetApi之前要通过((void**)ctx)[0]这种方式获取其地址
c++开发redis module问题之为什么在使用RedisModule_GetApi之前要通过((void**)ctx)[0]这种方式获取其地址
176 20
|
Rust NoSQL API
c++开发redis module问题之如果在加载module时,该module没有执行权限,Redis会如何解决
c++开发redis module问题之如果在加载module时,该module没有执行权限,Redis会如何解决
165 19
|
NoSQL API Redis
如何使用 C++ 开发 Redis 模块
如何使用 C++ 开发 Redis 模块
|
编解码 NoSQL Redis
c++开发redis module问题之想实现Redis命令,如何解决
c++开发redis module问题之想实现Redis命令,如何解决
|
NoSQL Java 编译器
c++开发redis module问题之保证Redis在fork时没有处于inflight状态的命令,如何解决
c++开发redis module问题之保证Redis在fork时没有处于inflight状态的命令,如何解决
|
NoSQL 编译器 Redis
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响
c++开发redis module问题之如果Redis加载了多个C++编写的模块,并且它们都重载了operator new,会有什么影响