一、什么是Redis:
Redis是一款高速缓存数据库,使用C语言编写,是key-value存储系统(键值存储系统);支持多种数据类型,如:string、list、set、zset、hash。可用于缓存、事件发布或订阅、高速队列等场景。基于内存并可做持久化处理
二、Redis常见数据类型
三、Redis持久化(重启恢复数据 AOF优先于RDB)
1、RDB快照:保存某个时间点的完整数据快照
RDB备份规则.png自动备份 :save seconds number(多久至少有多少个key发生改变)
手动备份 :save 或 bgsave
2、AOF:增量保存操作记录(append到文件末尾)
AOF备份规则.png自动备份:
开启aof备份: appendonly yes
手动备份:bgwriteaof
AOF重写规则:
当aof文件达到一定大小:auto-aof-rewrite-min-size 64mb 达到64M重写
当aof文件大小增大百分比:auto-aof-rewrite-percentage 100 增达达到100%
四、主从同步
1. 环境搭建(同一台机器)复制两份redis.conf配置文件 并修改如下项 redis6380.conf 和 redis6381.conf
配置文件列表.pngport 6380 #当前Redis使用端口号
pidfile /var/run/redis/redis6380.pid #进程文件
logfile /usr/local/redis/var/redis6380.log #日志文件
dbfilename dump6381.rdb #RDB持久化
replicaof 127.0.0.1 6379 #主Redis地址和端口
如果主Redis如果需要密码
masterauth <master-password>
2.启动redis6380和redis6381服务
redis-server ./redis6380.conf
redis-server ./redis6381.conf
3.查看主从服务信息(命令行中输入info )
- 从Redis信息
info
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
- 主Redis信息
info
# Replication
role:master
connected_slaves:2 #连接的从Redis数量
slave0:ip=127.0.0.1,port=6380,state=online,offset=15463,lag=0 #从Redis 地址 端口 状态 信息
slave1:ip=127.0.0.1,port=6381,state=online,offset=15463,lag=0
四、Redis Sentinel(哨兵)架构下的高可用
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
1. 配置Sentinel (新建配置文件sentinel.conf 并写入以下内容)
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
2. 启动模拟环境
#启动Redis
redis-server ./redis.conf #端口6379默认master
redis-server ./redis6380.conf #端口6380
redis-server ./redis6381.conf #端口6381
redis-server ./redis6382.conf #端口6382
#启动sentinel
redis-sentinel ./sentinel.conf
image.png
3. 模拟master 6379宕机情况
shutdown
image.png
四、Redis cluster集群
五、内存淘汰策略
1.最大内存设置
maxmemory 1048576
1.选择策略
# volatile-lru -> 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
# allkeys-lru -> 从数据集中挑选最近最少使用的数据淘汰
# volatile-lfu ->从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
# allkeys-lfu -> 从数据集中挑选使用频率最低的数据淘汰
# volatile-random -> 从已设置过期时间的数据集中任意选择数据淘汰。
# allkeys-random ->从数据集中任意选择数据淘汰
# volatile-ttl -> 从已设置过期时间的数据集中挑选将要过期的数据淘汰。
# noeviction -> 默认策略 不淘汰数据
五、Redis的单线程及其优点(处理每秒几十万的请求)
1. Redis的高并发和快速原因
- redis是基于内存的,内存的读写速度非常快;
- redis是单线程的,省去了很多上下文切换线程的时间;
- redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。
- 下面重点介绍单线程设计和IO多路复用核心设计快的原因。
2. 为什么Redis是单线程的
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了
- 不需要各种锁的性能消耗
Redis的数据结构并不全是简单的Key-Value,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash当中添加或者删除
一个对象。这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加。
总之,在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
- 单线程多进程集群方案
单线程的威力实际上非常强大,每核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的。
所以单线程、多进程的集群不失为一个时髦的解决方案。
- CPU消耗
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU。
但是如果CPU成为Redis瓶颈,或者不想让服务器其他CUP核闲置,那怎么办?
可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系数据库,数据之间没有约束。只要客户端分清哪些key放在哪个Redis进程上就可以了。
- 总结
Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快。
再说一下IO,Redis使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。
Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。
另外,数据结构也帮了不少忙,Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
还有一点,Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。
六、故障处理(缓存雪崩、缓存穿透、缓存击穿)
https://zhuanlan.zhihu.com/p/100706208
1、缓存穿透:在高并发下,查询一个不存在的值时,缓存不会被命中,导致大量请求直接落到数据库上,如活动系统里面查询一个不存在的活动。(1️⃣布隆过滤器解决,拦截一个一定不存在的值;2️⃣直接缓存一个NULL值
)
2、缓存击穿:在高并发下,对某一热点数据进行查询,但是这个时候缓存正好过期了,缓存没有命中,导致大量请求直接落到数据库上,如活动系统里面查询活动信息,但是在活动进行过程中活动缓存突然过期了。(首先get Key是否为null ,是的话,使用SETNX加锁,查库并set key,其余查询sleep(10)等待后再重新调用
)
3、 缓存雪崩:在高并发下,大量的缓存key在同一时间失效,导致大量的请求落到数据库上,如活动系统里面同时进行着非常多的活动,但是在某个时间点所有的活动缓存全部过期。(设定随机过期时间
)
解决方案
- 直接缓存NULL值:
当数据不存在时直接缓存NULL,时间不宜过长,60s为宜
- 限流:
常见的限流算法有滑动窗口,令牌桶算法和漏桶算法,或者直接使用队列、加锁等
- 缓存预热:
缓存命中时查看缓存有效期是否小于刷新时间,小于的话就刷新过期时间、可做到永不过期
- 分级缓存
- 缓存永远不过期
网友评论