安装Redis
1.主机环境配置
- 在
Redis
启动的日志中会有WARNING
提示设置一些OS内核
层面的参数调整
- 主要包括:
内存分配策略
、禁用交换分区
、Tcp队列长度
、禁用透明内存大页
1.1内存分配策略
- 程序运行需要申请内存,Linux允许对大部分申请内存的请求,以便能运行更多的程序
- 因此程序申请内存后并不会马上使用,这种技术叫做:
Overcommit
Linux
下Overcommit
有三种策略:
vlaue |
说明 |
0 |
表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程 |
1 |
表示内核允许分配所有的物理内存,而不管当前的内存状态如何。 |
2 |
表示内核允许分配超过所有物理内存和交换空间总和的内存 |
Redis
在Dump
数据时会fork
一个子进程
执行操作,子进程
理论上所占用的内存与父进程
一样
- 因此需要调整
Overcommit
为 1
,允许进程超量
使用内存空间
- 推荐
Redis
的maxmemory
不超过主机内存
的75%
,预留25%~30%
为宜
- 避免出现
Redis持久化
失败等问题
- 如何设置:
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
1.2禁用交换分区
Redis
的快
得益于
完全基于内存
高效的数据结构
单线程
基于IO多路复用
- 因此需要避免
Redis
的数据被交换
到低效
的交换分区
上
- 如何设置:
echo vm.swapiness=0 >> /etc/sysctl.conf
swapoff -a
1.3TCP队列长度
Redis
是基于IO多路复用
来支持高并发
的
- 因此需要调整
内核参数
来支持更多的client
与Redis
建立连接
- 众所周知,
TCP
需要三次握手
才能建立连接
- 在
三次握手
的过程中,Server
端会建立两个队列
存放半连接
和全连接
半连接队列
:(Incomplete connection queue),又称 SYN 队列
全连接队列
(Completed connection queue),又称 Accept 队列
半连接队列
: 当客户端发起 SYN 到服务端,服务端收到以后会回 ACK 和自己的 SYN。这时服务端这边的 TCP 从 listen 状态变为 SYN_RCVD (SYN Received),此时会将这个连接信息放入「半连接队列」,半连接队列也被称为 SYN Queue,存储的是 "inbound SYN packets"
全连接队列
: 全连接队列包含了服务端所有完成了三次握手,但是还未被应用调用 accept 取走的连接队列。此时的 socket 处于 ESTABLISHED 状态。每次应用调用 accept() 函数会移除队列头的连接。如果队列为空,accept() 通常会阻塞。全连接队列也被称为 Accept 队列
- 因此调整
半连接队列
和全连接队列
的大小就可以支持更多的TCP
链接
半连接队列
默认是2048
: cat /proc/sys/net/ipv4/tcp_max_syn_backlog
全连接队列
默认是128
: /proc/sys/net/core/somaxconn
- 显然
全连接队列
默认的128
有点小,一般需要增大至512~2048
全连接队列
的值受tcp-backlog
和somaxconn
共同控制的,取两者的最小值
- 所以你可以在
redis.conf
配置tcp-backlog
同时配置somaxconn
- 如何设置:
tcp-backlog: 1024
echo 2048 > /proc/sys/net/core/somaxconn
1.4透明内存大页
Transparent Huge pages(THP,透明大页) 自 RHEL 6 开始引入。由于传统的 Huge pages 很难手动的管理,对于程序而言,可能需要修改很多的代码才能有效的使用。THP 的引入就是为了便于系统管理员和开发人员使用大页内存。THP 是一个抽象层,能够自动创建、管理和使用传统大页。操作系统将大页内存看作是一种系统资源,在 THP 开启的情况下,其他的进程也可以申请和释放大页内存。
Huge pages 和 Transparent Huge pages 在大页内存的使用方式上存在区别,前者是预分配的方式,而后者则是动态分配的方式,显然后者更适合程序使用。需要注意的是,THP 虽然方便,但在某些场景种仍然会建议我们关闭,这个需要结合实际应用场景慎重考虑。
1.5Redis为什么禁用透明大页
Redis
在持久化
过程中会fork
一个子进程
来dump
数据
- 这涉及到
Linux
中fork
过程的CopyOnWrite机制
CopyOnWrite机制
: 在fork
出子进程
后,与父进程
共享内存空间
,两者只是虚拟空间
不同,但是其对应的物理空间
是同一个
- 当
父进程
的有写入更改数据时,会触发页异常中断
,内核会将异常
的页
复制一份,此时子父进程
各自持有独立
的一份
- 很明显如果
持久化
过程中,Redis
有大量的写入
则会有大量页面要修改
,就要拷贝
一个个2MB
的大页
- 会大幅增加重
Redis
写期间父进程
内存消耗
,同时每次写命令
引起的复制内存页单位为2MB
,会拖慢写操作的执行时间
,导致大量写操作慢查询
- 如何禁用:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
vim /etc/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
2.编译安装
- 官网有完整的安装文档,推荐参考官网文档安装
- 大致流程:
安装编译工具
--> 下载源码包
--> 解压
--> 编译
--> systemd托管
- 1.安装编译工具:
yum install make gcc gcc-c++
- 2.下载源码包: 最新Stable版本、历史版本
- 3.解压:
tar -xf redis-X.X.XX.tar.gz
- 4.编译:
make
# Redis默认使用jemalloc分配器,如果没有安装就会报错
# 默认的是 jemalloc, 因为 jemalloc 被证明 有更少的 fragmentation problems 比libc
# 两种解决方式
# 1. 安装 jemalloc
+ yum install https://rpmfind.net/linux/epel/7/x86_64/Packages/j/jemalloc-3.6.0-1.el7.x86_64.rpm
+ yum install https://rpmfind.net/linux/epel/7/x86_64/Packages/j/jemalloc-devel-3.6.0-1.el7.x86_64.rpm
# 2. 使用 libc 分配器
+ make MALLOC=libc
# 报错如下:
zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
#include <jemalloc/jemalloc.h>
# 创建Redis用户
groupadd redis
useradd -g redis -M -s /usr/sbin/nologin
# systemd
cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/path/to/redis/bin/redis-server /path/to/redis/redis.conf --daemonize no --supervised systemd
ExecStop=/path/to/redis/bin/redis-cli shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
3.Yum安装
Epel
源中默认是3.2.12
版本的,如果需要其他版本
的建议自己源码编译安装
Epel
:
yum install epel-release
yum clean
yum makecache
yum install redis