一、 Redis简介
- redis的优点
● 数据间没有必然的关联关系
● 内部采用单线程机制
● 高性能
● 多数据类型支持(String,Hash,List,Set,ZSet)
● 持久化支持(数据恢复) - redis的应用场景
● 为热点数据加速查询(热点商品、热点资讯等)
● 任务队列(秒杀、抢票等)
● 即时信息查询(排行榜、在线人数、微博粉丝数等)
● 时效性信息控制(验证码等)
● 分布式数据共享(分布式session)
● 分布式锁
● 消息队列
二、 数据类型的基本操作
- String类型
● 添加数据
set key value
● 获取数据
get key
● 删除数据
del key
● 添加/修改多个数据
mset key1 value1 key2 value2 ...
● 获取多个数据
mget key1 key2 ...
● 获取数据字符长度
strlen key
● 追加信息(原始信息存在就追加不存在就新建)
append key value
扩展操作
● 设置数值增加指定范围的值(分布式中id的自增)
incr key
incrby key increment
incrbyfloat key increment
● 设置数据减少指定范围的值
decr key
decrby key increment
● 设置数据具有指定的时效
setex key seconds value
psetex key millseconds value - Hash类型
存储对象类的数据,底层使用hash表结构实现(常应用于商品购物车的实现)
● 添加/修改数据
hset key value
● 获取数据
hget key field
hgetall key
● 删除数据
hdel key field1 field2 ...
● 添加/修改多个数据
hmset key field1 value1 field2 value2 ...
● 获取多个数据
hmget key filed1 field2 ...
● 获取hash表中字段的数量
hlen key
● 获取hash表中是否存在指定的字段
hexists key field
扩展操作
● 获取hash表中所有字段的名和值
hkeys key
hvals key
● 设置指定字段的数值数据增加指定范围的值
hincrby key field increment
hincrbyfloat key field increment - List类型
● 添加/修改数据
lpush key value1 value2 ...
rpush key value1 value2 ...
● 获取数据
lrang key start stop
lindex key index
llen key
● 删除并移除数据
lpop key
rpop key
扩展操作
● 规定时间内获取并移除数据
blpop key1 key2 ... timeout
brpop key1 key2 ... timeout
● 移除指定数据
lrem key count value - Set类型
● 添加数据
sadd key memer1 member2 ...
● 获取全部数据
smembers key
● 删除数据
srem key member1 member2
● 获取集合数据总量
scard key
● 判断集合中是否包含指定数据
sismember key member
扩展操作
● 随机获取集合中指定数量的数据
srandmember key count - SortedSet类型
● 添加数据
zadd key score1 member1 score2 member2 ...
● 获取全部数据
zrange key start stop withscores
zrevrange key start stop withscores
● 删除数据
zrem key member1 member2 ...
● 按条件获取数据
zrangebyscore key min max withscores limit
zrevrangebyscore key max min withscores
● 获取集合数据总量
zcard key
zcount key min max
三、 key的通用操作
● 删除key
del key
● 获取key是否存在
exists key
● 获取key的类型
type key
● 为key设置有效期
expire key seconds
pexpire key milliseconds
expireat key timestamp
pexpireat key millinseconds-timestamp
● 获取key的有效时间
ttl key
pttl key
● 将key从时效性转换为永久性
persist key
● 通配符查询key
key * 查询所有
key name* 查询所有以name开头的
key ?name 查询以一个任意字符开头的name结尾的
key n[ab]e 查询以n开头的e结尾的中间包含字母a或b的
四、 Redis持久化
为了防止数据的意外丢失,确保数据的安全性,需要对数据进行持久化。
Redis中的持久化分为两种方式RDB(快照)和AOF(过程日志)
RDB
以数据快照的方式进行存储
手动执行:
save命令:手动执行一次保存操作(每保存一次会生成一个.rdb文件)
会阻塞当前的Redis服务器,直到RDB过程完成为止,可能会造成长时间阻塞(不建议使用)
bgsave命令:手动启动后台保存操作,但不是立即执行,对阻塞问题进行了优化,Redis内部所有涉及到的RDB的操作都采用bgsave的方式
执行过程:
自动执行:
更改redis的conf目录下的redis.conf文件
# 指定端口号为6379
port 6379
# 设置redis后台运行
daemonize yes
# 指定日志文件
logfile "6379.log"
# 文件存储的位置
dir /redis/data
# 指定快照存储的名称
dbfilename dump-6379.rdb
# 设置压缩rdb
rdbcompression yes
# 对rdb的数据进行校验
rdbchecksum yes
# 每隔10秒有30次增删改则生成rdb文件
save 10 30
优点:
RDB是一个紧凑压缩的二进制文件,存储效率高,数据恢复速度比AOF更快
缺点:
无法做到实时持久化,可能会丢失数据,每次执行需要创建fork子进程,消耗性能
AOF
以独立日志的方式记录每次写命令,重启时再重新执行AOF中的命令,以达到恢复数据的目的,解决了数据持久化的实时性问题
AOF写数据过程:
描述:在redis客户端执行写操作,服务器接收到写操作之后,将写命令刷新到缓存区中,再通过某种策略,将命令同步到AOF文件中
AOF写数据的三种策略
● always:每次写入操作均同步到AOF文件中,数据零误差,性能较低
● everysec:每秒将缓存中的指令同步到AOF中,准确性较高,性能较高,在系统突然宕机时会丢失1秒的数据
● no:系统控制每次同步到AOF文件的周期,过程不可控
配置:
在(上面RDB的)redis.cnf文件中追加内容:
# 开启AOF支持
appendonly yes
# 指定写策略
appendfsync always
# 指定aof持久化的文件名
appendfilename appendonly-6379.aof
AOF重写
将对同一个数据的若干条命令执行结果转化为最终结果数据对应的指令进行记录
好处:降低磁盘占用空间,提高IO性能,提高数据恢复效率
重写规则:
● 手动重写:直接在客户端使用命令 bgwriteaof
● 自动重写:
自动重写触发条件设置
auto-aof-rewrite-min-size 70
auto-aof-rewrite-percentage 70
自动重写触发比对参数
aof_current_size
aof_base_size
自动重写触发条件
aof_current_size>auto-aof-rewrite-min-size
(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage
五、 Redis事务
事务执行示例:
# 开启事务,后续的命令将加入到事务队列中
multi
set name tom
set age 10
set gender male
# 如果发现加入事务队列的命令写错了,使用该命令来取消事务,该命令发生在multi之后,exec之前
discard
# 执行事务,和multi成对出现
exec
加入到事务队列中的命令并不会立即执行,只有在执行了exec命令后才开始执行
错误处理:
● 语法错误(命令格式有误)
如果定义的事务中所包含的命令存在语法错误,那么整个事务将不会执行
● 运行错误(指令格式正确,但无法正确执行)
能够正确运行的命令会执行,运行错误的命令不会执行,已经执行完毕的命令对应的数据不会自动回滚,需要程序员在代码中实现回滚
六、 Redis锁
加锁示例:
- 对key添加监视锁,在事务执行exec前如果数据发生了变化,会终止事务的执行(wath命令需要放在multi命令之前)
watch [key1] [key2] - 取消对所有key的监视
unwatch
分布式锁: - 使用setnx命令设置一个公共的锁,返回0表示设置失败,业务需排队或等待,返回1表示设置成功,执行业务操作
setnx lock-key value - 操作完成后,需通过del命令释放锁,以免后面请求无法获取锁
del lock-key
改良方案(为锁设置超时时间,一段时间后自动释放锁): - 设置锁
setnx lock-key value - 设置超时时间,expire为秒级,pexpire为毫秒级
expire lock-key [second]
pexpire lock-key [millsecond]
再次改良
使用lua脚本,使设置锁和设置超时时间成为一个原子操作
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
七、 Redis删除策略
● 定时删除(过期时间到达时,立即删除:降低内存,占用cpu)
● 惰性删除(过期时间到达时,不做处理,下次访问时进行删除:占用内存,节约cpu)
● 定期删除(周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度:cpu性能占用设置有峰值,检测频度可以自定义)
逐出算法:
redis在执行每一个命令之前会调用freeMemoryIfNeeded()检测内存是否充足,如果内存不满足新加入数据的最低存储要求,redis会临时删除一些数据为新数据存储腾出空间,这种策略称为逐出算法。(不保证100%清理出足够的空间,如不成功,则反复执行,仍不能达到则报错)
数据逐出策略:
配置:
在redis.conf文件中配置
maxmemory-policy [策略] 如:maxmemory-policy volatile-lru
八、 高级数据类型
bitmaps:一般用于信息状态统计
HyperLogLog:用于基数统计
GEO:用于地理坐标运算
九、 主从复制
主从复制避免了单点故障,提供了数据的冗余备份
一个master可以拥有多个slave,一个slave只对应一个master
读写分离职责:
master:负责写数据,并将数据同步到slave
slave:负责读数据
三个阶段:
● 建立连接
1.设置master的地址和端口,保存master信息
2.建立socket连接,发送ping命令
3.身份验证
4.发送slave端口信息
配置:
master配置
- master节点要求密码
requirepass [password]
slalve配置
在slavle节点的redis.conf文件下配置
slave联通master配置
slaveof [master的IP地址] [master的端口]
配置master的密码
masterauth [password]
● 数据同步
1.slave请求同步
2.master创建rdb同步数据
3.slave接收rdb,进行数据恢复
以上过程叫做全量复制
4.slave请求同步部分数据
5.slave接收复制缓冲区的数据,执行bgrewriteaof命令,恢复数据
以上过程叫做部分复制
image
数据同步阶段master说明
1.如果master数据量巨大,数据同步阶段应该避免流量高峰期,避免造成master阻塞,影响业务正常执行
2.复制缓冲区大小设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分赋值时发现数据已经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态,修改缓冲区大小操作如下
repl-backlog-size 1mb
3.master单机内存占用主机内存的比例不应过大,建议使用50-70%的内存,留下30-50%的内存用于执行bgsave命令和创建复制缓冲区
数据同步阶段slave说明
1.为避免slave进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务
slave-server-stale-data yes|no
2.数据同步阶段,master发送给slave信息可以理解master是slave的一个客户端,主动向slave发送命令
3.多个slave同时对master请求数据同步,master发送的RDB文件增多,会对带宽造成巨大冲击,如果master宽带不足,因此数据同步需要根据业务需求,适量错峰。
4.slave过多时,建议调整拓扑结构,由一主多从结构变为树状结构,中间接待你即是master,也是slave。注意使用树状结构时,由于层级深度,导致深度越高的slave与最顶层master间数据同步延迟较大,数据一致性变差,应谨慎选择
● 命令传播
image
主从复制工作流程完整版
image
十、 哨兵模式
哨兵:哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master
哨兵的作用
● 监控
不断地检查master和slave是否正常运行
master存活检测、master与slave运行情况检测
● 通知(提醒)
当被监控地服务器出现问题时,向其他(哨兵间,客户端)发送通知
image
● 自动故障转移
断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服务器地址
image
注意:哨兵也是一台redis服务器,只是不提供数据服务,通常哨兵配置数量为单数
十一、 集群
集群就是使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果。
image
image
image
十二、 故障及解决方案
缓存预热:系统启动前提前将相关的缓存数据直接加载到缓存系统,避免用户在请求的时候先查询数据库,然后再将数据缓存的问题。用户可以直接查询事先被预热的缓存数据
缓存雪崩:短时间内,大量的缓存集中失效,数据库同时接收到大量的请求无法处理,redis大量请求被积压,数据库崩溃。重启后仍然面对缓存中无数据可用,redis服务器资源被严重占用,最后redis服务器崩溃,导致集群坍塌。
解决办法:1.多级缓存 2.mysql是否存在严重耗时,对mysql进行优化 3.限流 4.过期时间设置为随机时间
缓存击穿:redis某个高热key过期瞬间,大量请求过来在redis中均未命中,直接压倒了数据库上
解决办法:1.预先设定热点key 2.多级缓存,设置不同的失效时间 3.设置为永久key
缓存穿透:大量访问一个不存在的数据,在跳过了合法数据在redis中的缓存阶段,每次都直接访问数据库
解决办法:1.对查询结果为null的数据缓存null值,并设定过期时间
2.黑白名单 3.布隆过滤器
网友评论