安装
redis是C语言编写的, 要先安装gcc编译器
yum -y install gcc automake autoconf libtool make
下载redis压缩包并解压到/usr/local/
wget http://download.redis.io/releases/redis-5.0.8.tar.gz
tar -zxvf redis-5.0.8.tar.gz -C /usr/local/
进入redis根目录, 编译redis代码
cd redis-5.0.8 && redismake
安装redis
make PREFIX=/usr/local/redis-5.0.8 install
安装完成后redis根目录下会新增bin目录, 里面放着redis的可执行文件
配置文件
redis根目录下创建conf目录统一存放配置文件,新建redis.conf配置文件
使用配置文件启动redis
./redis-server conf/redis.conf
基本配置参数说明
bind 127.0.0.1
限制访问IP
port 6379
访问端口
daemonize yes
后台启动
dir /usr/local/redis-5.0.8/data
工作目录
logfile "redis.log"
日志输出文件, 在工作目录中
maxmemory
最大占用内存
maxmemory-policy noeviction
淘汰策略
启动连接和关闭
启动redis服务有3种方式
- 直接使用bin目录下的
bin/redis-server
- 配置动态参数启动
bin/redis-server --port=6379
- 使用配置文件启动(推荐)
bin/redis-server conf/redis.conf
连接redis客户端
bin/redis-cli -h 127.0.0.1 -p 6379
正常关闭redis服务
bin/redis-cli.sh -h 127.0.0.1 -p 6379 shutdown
如果配置了密码, 连接和关闭时需要加上-a 参数, 如
bin/redis-cli -h 127.0.0.1 -p 6379 -a ${password} shutdown
常用命令
keys *
查询所有的key,比较耗时,不建议使用
dbsize
查询数据总数
exists key
查询key存不存在,1:存在 , 0 :不存在
expire key seconds
给key设置有效期, 单位s
ttl key
查询key的剩余有效时间, -1:永久有效,-2:无效的key或已删除
persist key
设置key永久有效
del key
删除key,1:删除成功,0:删除失败
type key
查看key的数据类型
info
查看服务器信息
常用数据类型
http://redis.cn/commands.html
redis为什么这么快
- 内存存储
- 单线程处理数据,避免上下文切换和静态消耗,FIFO,无需加锁
- 使用epoll模型,非阻塞IO
数据淘汰策略
volatile-lru
优先从设定了过期时间的数据中,删除长时间未使用的数据
allkeys-lru
从所有的数据中删除长时间未使用的数据
volatile-random
优先从设置了过期时间的数据中随机删除
allkeys-random
从所有数据中随机删除
volatile-lfu
从设置了过期时间的数据中,删除使用次数最少的数据
allkeys-lfu
从所有的数据中删除使用次数最少的数据
volatile-ttl
对设置了过期时间的数据进行排序,删除剩余有效时间最少的数据
noeviction
内存不足时抛异常,不会删除数据
数据持久化
RDB(快照)
快照是将内存中的数据通过序列化并进行压缩,然后存入硬盘中。重启redis时会读取rdb文件恢复数据。
触发方式:save命令(同步)
bgsave命令(异步)
配置同步策略
三种方式
自动触发机制:全量复制
debug reload
shutdown正常退出
会自动触发数据同步
配置:
save 60 10000
备份策略
dbfilename dump_6379.rdb
RDB备份文件
stop-writes-on-bgsave-error yes
是否在出现错误的时候终止RDB备份
rdbcompression yes
RDB备份文件是否进行压缩
缺点:
1)备份不及时,系统宕机可能会丢失数据
2)性能较差。RDB不是增量备份,每次备份都会把所有的数据传输到磁盘。AOF
AOF是把执行的命令写入到缓冲区,然后追加写入到磁盘中。通过读取并执行这些命令来恢复数据
备份策略:
always
每执行一条命令就备份到磁盘
everysec
每隔一秒备份一次
no
备份时机由操作系统决定
重写:对写入.aof文件的命令进行优化
配置:
appendonly yes
是否开启AOF备份模式
appendfilename "appendonly_6379.aof"
AOF备份文件
appendfsync everysec
AOF备份策略
no-appendfsync-on-rewrite yes
重写的时候是否执行AOF备份操作
auto-aof-rewrite-percentage 100
触发重写的文件大小增长百分比
auto-aof-rewrite-min-size 64m
触发重写的文件大小RDB和AOF混合模式
配置:
aof-use-rdb-preamble yes
使用RDB和AOF混合模式
主从复制
可以提高读数据的qps。设置方法:
方法1. 在需要设置为从节点的redis客户端使用命令
slaveof host port
方法2. 在配置文件中配置master的地址和端口
replicaof host port
哨兵机制
哨兵服务可以监测redis服务的运行状态,当有master服务器挂掉,会从剩余服务器中选举出新的master并修改其他slave服务器的master连接。
优点:可以解决单点故障,提高读数据的qps
缺点:无法提高写请求的qps,存储容量有局限性
配置
bind 127.0.0.1
限制访问IP
port 26380
访问端口
daemonize yes
后台启动
dir /usr/local/redis-5.0.8/data
工作目录
logfile "sentinel_26380.log"
日志输出文件, 在工作目录中
protected-mode no
是否开启保护模式
告诉sentinel去监听指定ip和port的一个master,master-name是集群的名字,quorum是指定当多少个sentinel认为这个master失效时,master才算真正失效
sentinel monitor ${master-name} ${ip} ${port} ${quorum}
master失效多长时间才会被sentinel认为是不可用的,单位毫秒,默认30秒
sentinel down-after-milliseconds master-name 30000
在发生failover主备切换时最多可以有多少个slave同时对新的master进行同步。这个数字越小,同步时间越长,数字越大,就有越多的slave因为replication操作而不可用。可以设置为1来保证同时只有一个slave不能处理请求
sentinel parallel-syncs ${master-name} 1
master服务器失效之后隔多长时间再次检查该服务器的状态
sentinel failover-timeout ${master-name} 180000
启动
bin/redis-sentinel conf/sentinel_26380.conf
集群
相对于哨兵机制:
- 有多台写服务器,可以提高写数据的qps
- 数据分散存储,提高数据量
- 提高带宽、网络流量
配置:
cluster-enabled yes
开启集群模式
cluster-config-file node_6379.conf
集群服务器的信息
cluster-node-timeout 15000
节点间通信超时时间
cluster-require-full-coverage no
集群中一个节点出现故障,是否停用整个集群
数据分区规则
顺序分区
特点:
1)数据容易倾斜
2)键值分布和业务相关
3)支持批量操作
4)可以顺序访问-
Hash分区
特点:
1)数据分散度高
2)键值分布与业务无关
3)支持批量操作
4)无法顺序访问Hash分区方案:
1)节点取余
根据Hash值 % 分区数量
进行分区
注意点:节点取余扩容时,为了减少数据的迁移量,尽量翻倍扩容(50%迁移量)2)一致性Hash
采用Hash环的概念,Hash结果是int类型,有0-2^32个数值,这些数值连在一起首尾相接形成一个环,在这个 环上均匀的分配节点,每个节点负责一块区域
当插入或查询一个key时,首先对key做Hash运算得到Hash值,然后根据这个Hash值顺时针找到对应的节点进行存储和读取
特点:
① 在客户端对key进行Hash运算,然后找到对应的节点进行存储和读取
② 扩容或者删除节点只会影响下一个相邻的节点,不会对其他节点产生影响
③ 翻倍扩容,扩容时在每块区域分别添加新的节点,以保证最小数据迁移量和负载均衡
④ 扩容后数据不会自动迁移,需要在客户端手动迁移数据。如果是缓存数据,可以从数据库查询之后再进行缓存,无需迁移数据,所以Hash环比较适合做缓存
3)虚拟槽
redis将16384个虚拟槽平均分配到节点服务器中,每个节点服务器都知道其他服务器中有哪些槽。操作时会对key进行CRC16(key) % 16383
运算,得到的结果就是所在的槽的编号,节点服务器接收到请求后,如果计算出来的槽在当前节点,就直接进行数据操作,如果不在当前节点,会连接到对应的服务节点进行操作。
集群搭建流程
- 配置并启动集群的服务器
从redis5版本官方提供了一个命令可以自动发现服务器、分配虚拟槽和设置从服务器,无需手动操作后面2 3 4 步
redis-cli --cluster create ${host1:port1 host2:port2 ...} --cluster -replicas ${slave_ratio}
slave_ratio
是从服务器占比,设置为2就是主从1:2,设置为3就是主从1:3
发现其他服务器
cluster meet ${host} ${port}
发现指定服务器
cluster nodes
或者cluster info
命令查看已发现的服务器信息分配虚拟槽
虚拟槽只分配给master服务器
虚拟槽一共16384个,可以通过脚本循环执行下面命令给指定服务器分配虚拟槽
redis-cli -h ${host} -p ${port} cluster addslots ${slot}
设置从服务器
redis-cli -h ${host} -p ${port} cluster replicate ${master_node_id}
master_node_id
可以通过cluster nodes
命令查看
Redis常见问题
缓存穿透:
缓存穿透一般出现在查询数据库中不存在的数据。缓存没有命中就会查数据库, 数据库查不到也不写入缓存,就会导致这个不存在的数据每次都要查询数据库,增加数据库的压力
解决方案:
1)单个key穿透,可以将这个key在redis中缓存一个空值,设置较短的有效期,防止高频率的查询数据库
2)多个key穿透,可以通过验证key的合法性来决定是否查询数据库。如果数据量不大,可以把所有的key放到redis的set集合中,查询时判断key如果在set集合中,再查数据库。如果数据量上亿,可以考虑使用布隆过滤器来实现。雪崩:
雪崩是指大量缓存在同一时间失效,所有的请求都会查询数据库,造成数据库崩溃。
解决方案:
1)尽量让key的过期时间均匀分布
2)控制同一个key查询数据库的线程数量,在查询数据库之前再次查询缓存。常见的限流算法有计数算法、滑动窗口、令牌桶、漏桶等
-
热点key:
热点key是指某个key的访问频率非常频繁,导致redis服务器压力剧增,无法保证正常提供服务
解决方案:
1)横向扩容,增加集群服务器提高读数据的能力
2) 使用本地缓存。把热点数据缓存在本地服务器的内存中,减少redis的访问量
SpringBoot项目集成Redis
- 导入redis包
spring-boot-starter-data-redis
和连接池包commons-pool2
- yml文件中配置redis
redis:
cluster:
nodes: 127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6384,127.0.0.1:6385,127.0.0.1:6386
lettuce:
pool:
min-idle: 10
max-idle: 10
max-active: 10
max-wait: 150000
- 使用redisTemplate操作redis
@Autowired
private RedisTemplate redisTemplate;
// 拿到ValueOperations对象操作redis
ValueOperations ops = redisTemplate.opsForValue();
String str = ops.get("key");