编译安装
1 | cd /usr/local/src |
配置文件
1 | daemonize yes # 后台运行 |
快速脚本
1 | sed -i 's#^daemonize.*#daemonize yes#' /etc/redis/6379.conf |
启动脚本
1 |
|
1 | chkconfig --add redis # CentOS |
修改内核参数
1 | tail /var/log/redis/redis.log |
1 | cat << EOF >> /etc/sysctl.conf |
redis的数据回写机制分为两种
同步回写即SAVE命令。redis主进程直接写数据到磁盘。当数据量大时,这个命令将阻塞,响应时间长
异步回写即BGSAVE命令。redis 主进程fork一个子进程,复制主进程的内存并通过子进程回写数据到磁盘。
由于RDB文件写的时候fork一个子进程。相当于复制了一个内存镜像。当时系统的内存是4G,而redis占用了
近3G的内存,因此肯定会报内存无法分配。如果 「vm.overcommit_memory」设置为0,在可用内存不足的情况
下,就无法分配新的内存。如果 「vm.overcommit_memory」设置为1。 那么redis将使用交换内存。
关闭透明内存 Transparent Huge Pages (THP)
告警,这是一个关于透明内存巨页的话题。简单来说内存可管理的最小
单位是page,一个page通常是4kb,那1M内存就会有256个page,CPU通过内置的内存管理单元管理page表
记录。Huge Pages就是表示page的大小已超过4kb了,一般是2M到1G,它的出现主要是为了管理超大内存。
个人理解上TB的内存。而THP就是管理Huge Pages的一个抽象层次,根据一些资料显示THP会导致内存锁
影响性能,所以一般建议关闭此功能。
1 | cat kernel transparent_hugepage/enabled |
持久化
RDB模式
RDB是redis对数据进行持久化而保存到硬盘的数据文件。(默认)
工作原理
当redis生成dump.rdb文件时,工作过程如下:
redis主进程fork一个子进程
fork出来的子进程将内存的数据集dump到临时的RDB中
当子进程对临时的RDB文件写入完毕,redis用新的RDB文件代替旧的RDB文件
默认情况下相关配置如下:1
2
3save 900 1
save 300 10
save 60 10000
其意义为:1
2
3当1个key更新值时每900秒保存一次数据到硬盘
当10个key更新值时每300秒保存一次到硬盘
当10000个key更新值时每60秒保存一次到硬盘
换句话说,当你重启服务器时数据是可能会丢失的,如果数据量小的时候,你会丢失5分钟以内的数据;如果数据量大的时候,你会丢失一分钟以内的数据。
所以set name 1后重启服务器,get name时的结果会是nil,如果你想避免这种情况发生,那么可以save后重启服务器。
然而大多数情况下我们需要防止的是服务器突发情况下的重启,这时候可能没有机会save,所以还是会造成数据的丢失。所以你可以设置save “”这样的话会每次写操作到保存到硬盘,但是redis作为缓存却需要每次到保存到硬盘已丧失了其作为缓存的意义,因此这种方法是不可取的。
还有一种方式,在每次写操作时使用bgsave命令,可以直接返回操作结果并异步将其保存到硬盘。
rdb方式的优点是保存的数据存储量小(只有数据)重启速度很快;缺点是可能会造成数据的丢失。
AOF模式
aof本质是redis操作(写操作)日志文件。aof默认是未开启的,需要在配置文件中进行设置,在配置文件中将这一行改为appendonly yes就可以了。
工作原理 1
2
3AOF :append only file。
每当Redis执行一个改变数据集的命令时,这个命令都会被追加到AOF文件的末尾。
当redis重新启动时,程序可以通过AOF文件恢复数据。
那么会在什么时候append到文件末尾呢?有三种方式:1
2
3
4
5
6
7
8
9#appendfsync always
appendfsync everysec
#appendfsync no
appendfsync always 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
appendfsync everysec 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
appendfsync no # 从不 fsync 将数据交给操作系统来处理。更快,也更不安全的选择。
推荐默认appendfsync everysec 每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
aof能够保证数据的安全,但是在重启时比较耗时,而且aof文件的体积比rdb文件大。
使用
在同时开启rdb和aof模式时,会采用aof模式来读取数据。在正常的使用中,如果不是十分在乎短时间内的数据丢失的时候,使用rdb方式会使服务器的效率更高,更节省cpu和硬盘;如果担心数据丢失的话,aof方式无疑会是更好的选择。
在线动态从RDB切换为AOF
切勿修改配置文件重启,这样会丢失所有数据的。
正确的操作方式如下1
2
3
4
5
6config set appendonly yes
config set save "" #关闭,不关闭会增加io压力
vim /etc/redis/6379.conf
save "" # 关闭RDB
appendonly yes # 开启AOF
主从复制
1、概述
Redis的replication机制允许slave从master那里通过网络传输拷贝到完整的数据备份。具有以下特点:
1.异步复制,从2.8版本开始,slave能不时地从master那里获取到数据。*
2.允许单个master配置多个slave*
3.slave允许其它slave连接到自己。一个slave除了可以连接master外,它还可以连接其它的slave。形成一个图状的架构。*
4.master在进行replication时是非阻塞的,这意味着在replication期间,master依然能够处理客户端的请求。*
5.slave在replication期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,如果配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会拒绝客户端的请求和连接。*
6.一般使用replication来可以实现扩展性,例如说,可以将多个slave配置为“只读”,或者是纯粹的数据冗余备份。*
7.能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行持久化操作(把配置文件中持久化相关的配置项注释掉即可),然后连接上一个slave,这个slave则被配置持久化选项。不过需要注意的是,在这个方案中,必须确保master不会自动启动。
2、Master持久化功能关闭时Replication的安全性
当有需要使用到replication机制时,一般都会强烈建议把master的持久化开关打开。即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也应该把master配置为不会自动启动的。
为了更好地理解当一个不进行持久化的master如果允许自动启动所带来的危险性。可以看看下面这种失败情形:
假设我们有一个redis节点A,设置为master,并且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据。
如果A节点崩溃了导致所有的数据都丢失了,它会有重启系统来重启进程。但是由于持久化功能被关闭了,所以即使它重启了,它的数据集是空的。
而B和C依然会通过replication机制从A复制数据,所以B和C会从A那里复制到一份空的数据集,并用这份空的数据集将自己本身的非空的数据集替换掉。于是就相当于丢失了所有的数据。
即使使用一些HA工具,比如说sentinel来监控master-slaves集群,也会发生上述的情形,因为master可能崩溃后迅速恢复。速度太快而导致sentinel无法察觉到一个failure的发生。
当数据的安全很重要、持久化开关被关闭并且有replication发生的时候,那么应该禁止实例的自启动。
3、replication工作原理
如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个SYNC命令给master请求复制数据。
master收到SYNC命令后,会在后台进行数据持久化,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份数据集发送给slave,slave会把接收到的数据进行持久化,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。
当master与slave之间的连接由于某些原因而断开时,slave能够自动重连master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。
当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,支持部分复制。
4、数据部分复制
从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。
master会在其内存中创建一个复制流的等待队列,master和它所有的slave都维护了复制的数据下标和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果进程id变化了,或者数据下标不可用,那么将会进行一次全部数据的复制。
5、支持部分数据复制的命令是PSYNC
不需硬盘参与的Replication
一般情况下,一次复制需要将内存的数据写到硬盘中,再将数据从硬盘读进内存,再发送给slave。
对于速度比较慢的硬盘,这个操作会给master带来性能上的损失。Redis2.8版本开始,实验性地加上了无硬盘复制的功能。这个功能能将数据从内存中直接发送到slave,而不用经过硬盘的存储。
不过这个功能目前处于实验阶段,还未正式发布。
6、主从配置
slave节点配置文件1
2slaveof 192.168.1.41 6379
masterauth MbGlEnjqZ2Op+2HeLETjm@IT #若master通过requirepass配置了密码,则需要配置此项
7、只读的slave
从redis2.6版本开始,slave支持只读模式,而且是默认的。可以通过配置项slave-read-only来进行配置,并且支持客户端使用CONFIG SET命令来动态修改配置。
只读的slave会拒绝所有的写请求,只读的slave并不是为了防范不可信的客户端,毕竟一些管理命令例如DEBUG和CONFIG在只读模式下还是可以使用的。如果确实要确保安全性,那么可以在配置文件中将一些命令重新命名。
也许你会感到很奇怪,为什么能够将一个只读模式的slave恢复为可写的呢,尽管可写,但是只要slave一同步master的数据,就会丢失那些写在slave的数据。不过还是有一些合法的应用场景需要存储瞬时数据会用到这个特性。1
slave-read-only yes
8、至少N个slave才允许向master写数据
从redis2.8版本开始,master可以被配置为,只有当master当前有至少N个slave连接着的时候才接受写数据的请求。
然而,由于redis是异步复制的,所以它并不能保证slave会受到一个写请求,所以总有一个数据丢失的时间窗口存在。
这个机制的工作原理如下所示:
- slave每秒发送ping心跳给master,询问当前复制了多少数据。
- master会记录下它上次收到某个slave的ping心跳是什么时候。
- 使用者可以配置一个时间,来指定ping心跳的发送不应超过的一个超时时间
- 如果master有至少N个slave,并且ping心跳的超时不超过M秒,那么它就会接收写请求。
也许你会认为这情形好似CAP理论中弱化版的C(consistency),因为写请求并不能保证数据的一致性,但这样做,至少数据丢失被限制在了限定的时间内。即M秒。
如果N和M的条件都无法达到,那么master会回复一个错误信息。写请求也不会被处理。
有两个配置项用来配置上文中提到的N和M:1
2min-slaves-to-write <number of slaves>
min-slaves-max-lag <number of seconds>
常用命令
1 |
|
压力测试
1 | # 测试SET 随机数性能 |
https://segmentfault.com/a/1190000006619753#articleHeader0
https://www.imooc.com/article/69685?block_id=tuijian_wz
https://www.jianshu.com/u/baad5ee99ca9
redis压力测试