安装
单机安装
-
1、下载上传解压:redis-6.0.10.tar.gz
-
2、需要gcc版本5.3及以上版本,升级gcc
sudo yum -y install centos-release-scl
sudo yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
sudo scl enable devtoolset-9 bash
#注意:scl命令启用只是临时的,推出xshell或者重启就会恢复到原来的gcc版本。
#如果要长期生效的话,执行如下:
echo “source /opt/rh/devtoolset-9/enable” >>/etc/profile -
3、编译:
cd /home/msy/install/redis-6.0.10
make -
4、安装:
#PREFIX前缀就是redis安装目录,会在redis安装根目录下生成一个bin目录
make install PREFIX=/home/msy/install/redis-6.0.10/ -
5、修改配置文件:
#为了启动方便,将redis.conf拷贝到bin目录下
cd redis.conf bin/
vim /bin/redis.conf
(注意以下的配置)
#绑定的ip
bind 10.10.96.247
#关闭保护模式
protected-mode no
#端口
port 6379
#守护进程的方式
daemonize yes
#log文件
logfile /home/msy/install/redis-6.0.10/redis-log
#rdb持久化的时机
save 900 1
save 300 10
save 60 10000
#rdb文件
dbfilename dump.rdb
#pidfile文件
pidfile /home/msy/install/redis-6.0.10/redis_6379.pid
#目录(最好修改,默认是 ./ 是在当前启动目录下)
dir /home/msy/install/redis-6.0.10/
#密码,暂不设置
#requirepass 123
#开启aof持久化
appendonly yes
#aof文件名
appendfilename appendonly.aof
#aof刷盘机制:1秒一次(建议用这个,默认的)
appendfsync everysec
#指当前aof文件比上次重写的增长比例大小(100%),达到这个大小就进行 aof 重写
auto-aof-rewrite-percentage 100
#最开始aof文件必须要达到这个文件时才触发aof重写,后面的每次重写就不会根据这个变量了
auto-aof-rewrite-min-size 64mb
#开启混合持久化(需要同时开启rdb和aof)
aof-use-rdb-preamble yes
#lazyfree机制,建议开启
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes
lazyfree-lazy-user-del yes -
6、启动、关闭
cd bin
#后台启动,以守护进程的方式
./redis-server redis.conf
#关闭redis
./redis-cli -h 10.10.96.247
#进去之后
shutdown
exit -
7、设置开机自启动脚本
在redis安装目录下有一个 utils/redis_init_script 的一个启动脚本,我们可以基于这个脚本做一些修改。首先打开这个脚本,我们可以看到这里主要是这么几个参数比较重要:
REDISPORT:表示redis的端口号
EXEC:redis-server所在的目录,这里我们是在bin目录下,所以应该改为:/home/msy/install/redis-6.0.10/bin/redis-server
CLIEXEC:redis-cli所在的目录,这里我们也是在bin目录下,所以应该改为:/home/msy/install/redis-6.0.10/bin/redis-cli
PIDFILE:这个表示redis启动的时候会生成一个pidfile文件,关闭的时候会删除这个文件,用来判断redis是否运行状态,这里根据redis.conf的配置文件来看,应该改为:/home/msy/install/redis-6.0.10/redis_6379.pid
CONF:这个表示redis配置文件所在的目录,所有应该改为:"/home/msy/install/redis-6.0.10/bin/redis.conf"
#!/bin/sh # # Simple Redis init.d script conceived to work on Linux systems # as it does use of the /proc filesystem. ### BEGIN INIT INFO # Provides: redis_6379 # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Redis data structure server # Description: Redis data structure server. See https://redis.io ### END INIT INFO REDISPORT=6379 EXEC=/usr/local/bin/redis-server CLIEXEC=/usr/local/bin/redis-cli PIDFILE=/var/run/redis_${REDISPORT}.pid CONF="/etc/redis/${REDISPORT}.conf" case "$1" in start) if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." $EXEC $CONF fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." $CLIEXEC -p $REDISPORT shutdown while [ -x /proc/${PID} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done echo "Redis stopped" fi ;; *) echo "Please use start or stop as first argument" ;; esac
修改之后我们把该配置文件复制到 /etc/init.d目录下,然后重命名,修改权限,加入自启动
sudo cp redis_init_script /etc/init.d
sudo cd /etc/init.d
mv redis_init_script redisd
sudo chmod 777 redisd
sudo chkconfig redisd on
然后需要在该启动脚本开头加上下面这两行# chkconfig: 2345 90 10 # description: Redis is a persistent key-value database
-
8、然后我们就可以通过 service redisd start 来启动redis,同时redis也会在开机的时候自启动,但是在通过 service redisd stop 来关闭redis的时候发现报错,错误信息为:连接不上127.0.0.1的redis服务,于是再次查看脚本 发现 stop的时候是通过 redis-cli -p 6379来关闭的,由于我们配置文件中修改了 bind 10.10.96.247,所以需要修改下stop时候的脚本,添加一个参数
HOST=10.10.96.247
,然后修改为$CLIEXEC -h $HOST -p $REDISPORT shutdown
。(注意:如果你的redis配置了密码,这里需要加上 -a [密码] )即可。 -
9、至此,redis的单机安装,相关配置文件修改,开机启动脚本,开始关闭脚本都配置好了,这里我是以非root用户操作的。
主从+哨兵搭建
- 1、主节点配置不变
- 2、从节点修改redis.conf,添加如下配置
vim redis.conf
#绑定的ip
replicaof 10.10.96.247 6379
masterauth 123 - 3、分别启动主从,从节点默认只读
- 4、哨兵搭建
cp sentinel.conf /bin
cd bin
vim sentinel.conf
#绑定的ip
bind 172.16.157.201
port 26379
protected-mode no
daemonize yes
pidfile /home/msy/install/redis-6.0.10/sentinel_26379.pid
logfile /home/msy/install/redis-6.0.10/sentinel_log
dir /home/msy/install/redis-6.0.10/
sentinel monitor mymaster 172.16.157.201 6379 2
#如果redis设置了密码,这个配置一定要配上,而且这个配置要在 sentinel monitor 之后,不然报错(亲测遇到过)
#sentinel auth-pass mymaster 123
sentinel down-after-milliseconds mymaster 10000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
(从节点也这样操作,注意bind不一样) - 5、分别启动三个哨兵
cd bin
./redis-sentinel sentinel.conf - 6、设置开启自启动脚本,同redis的启动脚本,在 /etc/init.d 目录下。复制一份 redisd 改名为 sentineld,修改如下内容:REDISPORT=26379。EXEC=/home/msy/install/redis-6.0.10/bin/redis-sentinel。PIDFILE=/home/msy/install/redis-6.0.10/sentinel_${REDISPORT}.pid。CONF="/home/msy/install/redis-6.0.10/bin/sentinel.conf"。我相信为什么改这几个参数应该很好理解,只要你能看的懂这个脚本就行。同样的把这个脚本加入开机自启动。
- 7、后面开启关闭sentinel的话就用命令: service sentineld start|stop
集群搭建
常用数据类型及应用场景:
-
String:字符串
内部编码:
int:8个字节的长整型
embstr:<=44字节的字符串
raw:>44字节的字符串
场景:
缓存功能 计数器 共享用户Session -
Hash
内部编码:
外层是hashtable
内层是ziplist和hashtable
场景:
缓存 库存 爆品 -
list
多个有序字符串的集合
内部编码:
3.0之前是ziplist和linkedlist
3.2之后是quicklist
场景:
存储列表结构-粉丝列表,好友列表,文章评论 -
set
多个无序不重复的字符串集合
内部编码:
整数集合(intset)或哈希表(hashtable)
场景:
自动去重 数据集玩法:共同好友,你可能认识 -
zset
和set一样,但是有排序,为每个元素设置一个分数作为排序依据
内部编码:
压缩列表(ziplist)或跳跃表(skiplist)
场景:
topN 热搜-标题名加热度值
高级数据类型
- bitmap
统计用户在线状态,如果在线则设置为1,不在线为0。
setbit key [用户id,必须为数字] [0或者1]
bitcount key - hyperLogLog
统计UV,得到不重复的元素个数。
pfadd key a
pfcount key
pfmerge key1 key2 key3 - geospatial
做附近的人功能 geoadd key [经度] [纬度] [名称]
GEOADD cities 116.404269 39.91582 “beijing” 121.478799 31.235456 “shanghai”
GEORADIUS cities 120 30 500 km
Redis持久化
-
RDB
以快照的形式,当复合一定条件时将数据写入磁盘,是一个二进制文件,Redis的默认持久化方式。
触发时机:手动命令、符合配置的快照规则、主从复制时
手动命令:sava、bgsave.
save会阻塞redis服务器,执行命令期间,redis不能处理客户端的请求。
bgsave是主进程会fork一个子进程异步做快照,只有在fork的时候才会阻塞,阻塞过程很短。
快照规则:save 900 1 | save 300 10 | save 60 10000 -
AOF
将redis命令追加到aof文件中
配置规则:always、everysec、no 一般配置一秒操作一次。
AOF的重写:aof文件会很大,如果配置了重写,在达到配置要求时会重写aof文件,会对一些命令做 优化合并,减少aof文件大小,它也是fork一个子进程;下面的配置表示:第一次重写的时候是AOF文件达到64mb后续的重写是在前一个AOF文件大小增加了100%就发生重写。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb -
两个优缺点比较和选择:
RDB恢复快,对redis性能影响小;但是数据会丢失。
AOF数据更全,最多丢失1秒的数据,追加操作写入性能高;但是文件很大,恢复速度没有RDB快,对redis性能影响上比RDB大,但依然还是很快。
选择上:一起使用,恢复的时候 优先以aof文件为主。 -
Redis在4.0之后新增了混合化持久化方式
当前数据以RDB的形式写入文件开头,后续用AOF的方式追加命令。
开启方式:aof-use-rdb-preamble yes 5.0以后默认开启,之前的版本要手动开启。
Redis 数据恢复
可以每小时、每天 对dump.rdb 文件做备份,然后恢复的时候,如果只是redis进程挂了,直接重启redis;如果redis的appendonly.aof和dump.rdb文件都坏了且不可恢复(这种情况基本都是r人为的),则可以基于最近的一小时备份文件做恢复。操作如下:
- 首先拷贝备份的dump.rdb文件到redis中,然后要关闭appendonly。因为如果appendonly和rdb都开启的话,恢复的时候是以appendonly.aof为主,而重启后会生成一个新的appendonly.aof文件,此文件没有内容,所以redis重启后不会恢复任何数据。
- 重启redis,此时数据肯定是恢复过来的.
- 热修改appendonly属性,config set appendonly yes,此时会在redis目录下生成一个appendonly.aof文件,这个文件内容和dump.rdb一样(因为我们配置的是混合持久化,它的特点就是当前数据以rdb的形式写入,也从侧面印证了我们的混合持久化是开启成功的)。
- 然后修改 redis.conf 配置文件,将 appendonly 改为 yes ;然后再次重启redis,也就是调用
- 然后我们发现数据都恢复过来了,因为此时是基于我们之前生成的有数据的 appendonly.aof文件来恢复的,它里面的数据就是dump.rdb中是一样的,所以全部的数据都恢复成功了。然后继续添加新的key的时候,会往appendonly.aof文件中追加命令(同样印证了混合持久化的方式)。
- 至此,我们的数据就已经从备份的dump.rdb文件中恢复了。
Redis过期策略和内存淘汰策略
Redis4.0新增了一个lazy free特性,可以理解为延迟删除或者惰性删除,意思就是在删除的时候可以异步延迟释放键值,把键值的释放操作放在一个BIO单独的子线程中处理,以减少删除对Redis主线程的阻塞,可以避免删除big key时带来的性能问题。
-
主动删除
UNLINK命令,他是lazy free的一个实现;而DEL命令是阻塞的 -
被动删除
比如过期key的删除、超过内存时的删除
目前有四个配置,默认都是关闭的,建议开启这些配置
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
lazyfree-lazy-eviction:表示当 Redis 运行内存超过最大内存时,是否开启 lazy free 机制删除;
lazyfree-lazy-expire:表示设置了过期时间的键值,当过期之后是否开启 lazy free 机制删除;
lazyfree-lazy-server-del:有些指令在处理已存在的键时,会带有一个隐式的 del 键的操作,比如rename 命令,当目标键已存在,Redis 会先删除目标键,如果这些目标键是一个 big key,就会造成阻塞删除的问题,此配置表示在这种场景中是否开启 lazy free 机制删除;
slave-lazy-flush:针对 slave(从节点) 进行全量数据同步,slave 在加载 master 的 RDB 文件前,会运行 flushall 来清理自己的数据,它表示此时是否开启 lazy free 机制删除。 -
限制最大内存:64位系统中Redis内存大小是没有限制的,需要配置下 maxmemory 参数,单位 bytes。
-
超过最大内存后,Redis就会执行自己的内存淘汰策略:
noeviction:不淘汰任何数据,当内存不足时,新增操作会报错,Redis 默认内存淘汰策略。
LRU:历史访问记录来进行淘汰数据,也就是把最久不访问的数据优先淘汰。
可以对所有的key设置,也就是allkeys-lru;
也可以只对设置了ttl失效时间的key设置,也就是volatile-lru。
LFU:在一段时间内,数据被使用频次最少的,优先被淘汰(4.0新增的)
可以对所有的key设置,也就是allkeys-lfu;
也可以只对设置了ttl失效时间的key设置,也就是volatile-lfu。
随机淘汰:allkeys-random:随机淘汰任意键值;
volatile-random:随机淘汰设置了过期时间的任意键值。
volatile-ttl:优先淘汰更早过期的键值。 -
定期删除+惰性删除
定期删除:指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。
惰性删除:在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了,如果过期就会删除,不返回任何东西。
Redis集群演变
-
主从复制
Redis 的主从同步,分为全量同步和增量同步。
只有从机第一次连接上主机是全量同步。
断线重连有可能触发全量同步也有可能是增量同步( master 判断 runid 是否一致)。
除此之外的情况都是增量同步。
在Redis2.8版本后,主从断线后恢复的情况下实现增量复制。
配置: # replicaof
#4.0之前只能slaveof 4.0之后默认replicaof,slaveof都起作用
slaveof 192.168.133.154 6379
replicaof 192.168.133.154 6379 -
主从复制+哨兵机制
监控: 哨兵会不断地检查你的 Master 和 Slave 是否运作正常。
提醒:当被监控的某个 Redis 节点出现问题时, 哨兵可以通过 API向管理员或者其他应用程序发送通知。
自动故障迁移:当一个 Master 不能正常工作时,哨兵会开始一次自动故障迁移操作。 -
Redis-Cluster
架构细节
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
Redis 集群中内置了 16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
容错
(1)集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉。
(2)半数以上master挂掉,集群进入fail状态。
(3)slot中某一段的主从节点都挂掉,集群进入fail状态。
(4)最少三主三从.
Redis事务
redis事务是一个单独的隔离操作,事务中所有命令都会序列化、按顺序的执行,事务在执行过程中,不会被客户端其他发送来的命令请求所打断。
redis事务的主要作用就是串联多个命令防止其他命令插队。更类似一个批量执行的指令。
队列中的命令没有提交之前都不会实际执行。
不保证原子性,如果同一个事务中如果有一条命令执行失败,其后的命令任然会被执行,没有回滚。
注意:如果Redis Cluster模式下,不建议用事务,因为多个key的写入按照slot分之后可能分布在多个节点上。
Redis常见问题
- 缓存雪崩:大量的key同时失效,高并发下对DB的请求会增大。
让缓存失效时间打散,均匀分不开来。 - 缓存穿透:对不存在的key高并发查询,查询的请求会发到DB上,导致数据库压力增加。
采用布隆过滤器,用一个bitmap存所有的key,每次请求都先查询bitmap中是否 有这个key。 - 缓存一致性问题:
1.先更新DB再删除redis
2.先删除redis再更新DB
都会有脏数据产生的可能,可以采取延迟双删的策略:
先删除redis,再更新DB,再睡眠一段时间(比如1s)再次删除redis。可以防止在删除redis和更新DB之间来了一个读请求,它查询redis没有然后读取数据库中旧数据再更新到redis中去。 - redis分布式锁:后续单独写分布式锁的文章来讲这个。