redis-6.0.6.tar.gz
tar -zxvf redis-6.0.6.tar.gz
#安装gcc依赖
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
#进入文件夹编译
make
make install
#修改redis.conf
daemonize yes #后台运行
requirepass root #需要密码连接
#进入src文件夹
./redis-server redis.conf #启动
./redis-cli -p 6379 -a root #连接
# 单值缓存
SET key value
GET key
# 对象存储
1、SET user:1 value(JSON格式数据)
2、MSET user:1:name zhuge user:1:balance 1888
MGET user:1:name user:1:balance
# 分布式锁
SETNX product:10001 true //返回1代表取锁成功,返回0代表失败
DEL product:10001 //执行完业务释放锁
SET product:10001 true ex 10 nx //防止程序意外终止导致死锁
# 计数器
INCR article:readcount:{文章id}
# web集群session共享
spring session + redis
# 分布式系统全局序列号
INCRBY orderId 1000
# 以用户id为key,商品id为字段
hset user:1 1001 1 # 添加商品
hincrby user:1 1001 1(-1) #加1或者-1
hdel user:1 1001 #删除商品
hlen user:1 #长度
hkeys user:1 #获取所有的字段
hgetall user:1 #获取所有字段和值
hscan user:1 0 match * count 5 #截取范围字段
SINTER set1 set2 set3 #交集
SUNION set1 set2 set3 #并集
SDIFF set1 set2 set3 #差集
实现排行榜
7日热榜
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bDtpDpgi-1618544331765)(images/image-20210204162625216.png)]
所有的数据都在内存当中,单线程避免了线程上下文的切换(一但上下文的切换就涉及用户态向内核态的转换,并且还会把线程栈中的数据全部挂到主内存中的TSS任务状态段中保存数据)
redis-server采用了io多路复用
keys:在生产环境中会导致cpu使用率极高,解决方案将需要用到的key放到set中统一维护
scan:代替掉keys命令,类似分页查找key
info:查看redis的状态信息
将数据的日志快照保存到drmp.rdb的文件里面。
快照策略:
客户端可以手动执行快照save和bgsave:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2aov4LEW-1618544331767)(images/image-20210204164142399.png)]
每执行一条指令都记录进appendonly.aof(采用resp格式)当中,会导致性能问题,因为每次都会跟磁盘做一次交互。重启的时候为一条一条的执行AOF的命令,redis会优先恢复aof再恢复rdb,aof的数据比较安全
AOF文件里面可能会有很多相同或者无用的指令,比如incr a命令执行6次,文件中会重写成set 6
配置AOF重写:
bgrewriteaof:手动重写
AOF重写redis会fork出一个子进程来进行重写数据,其它命令阻塞也是阻塞在fork,但是会很快
使用RDB、AOF混合的方式进行持久化。在重写时不会再单纯的将数据转换为RESP格式,而是先把数据转换为RDB二进制压缩格式,然后存入到AOF当中
#复制sentinel.conf文件
cp -R sentinel.conf sentinel-26379.conf
cp -R sentinel.conf sentinel-26380.conf
cp -R sentinel.conf sentinel-26380.conf
#修改哨兵配置
sentinel monitor mymaster 192.168.60.46 6380 2 #redis主节点的地址
sentinel auth-pass mymaster root #连redis时的密码
dir '' #持久化文件地址
logfile '' #日志地址
pidfile '/var/run/redis-sentinel-26379.pid' #进程文件地址,每一个sentinel都对应一个
#redis配置,主从配置的密码都需要
requirepass root #要求密码登陆
masterauth root #连接主节点的密码
哨兵架构
多主从高可用架构
数据分片规则:hash slot(hash槽)对key值进行hash运算根据16384进行取模(CRC(key)%16384),redis会按照计划对槽位进行默认分配,只有主节点进行分配槽位
为什么redis的hash slot会设计成16384?
通信:gossip协议
心跳机制:ping各个节点做心跳机制,让节点间可以进行通信(去中心化)
配置:cluster-node-timeout,如果节点通信时间超过当前设置,就意味着下线,下线就会触发master进行选举,一般时间不能太短5秒
为什么master推荐奇数?
主要是通过节省机器资源角度,如果3个master节点挂2个没法选举master了,如果4个master挂2个也不能选举master
如果一段slot的分片全部挂了,如何提供服务?
如果一个小集群全部挂了,整个集群就不能提供服务了。需要修改配置才能提供服务cluster-require-full-coverage为no时,一个小集群挂掉了仍然可以访问。
批量命令是否支持?
如果key的slot落在同一个区域就可以,如果不在同一个区域,就会报错。
支持批量操作的技巧例子:mset {user1}:id 1 {user1}:name zzzz {user1}:balance 1000
三个节点,每个节点,一主一从。
#修改配置文件 6379/redis-6379.conf
port 6379
pidfile '' #进程文件每一个都要配置成唯一
logfile '' #日志文件路径
dir '' #持久化文件路径
cluster-enable yes #打开集群支持
cluster-node-timeout #防止网络抖动,每个节点间通信时间设置为5秒
requirepass root #登陆节点密码
masterauth root #从节点连接主节点需要验证
redis-cli create --cluster-replicas 1 ip:port ip:port
说明:–cluster-replicas 1 代表每个小集群需要配置几个从节点,如果为1,那么每个主节点就配置一个从节点,总过需要6个redis,如果为2总共需要9个redis服务
说明:每个添加的新节点都是主节点
删除节点前,需要将删除节点的数据放到其它节点中
优点:
缺点:
可以一次性发送多个命令到redis,并不是原子性操作,如果命令过多还是会处理过慢
特点:同时对所有的节点发送加锁命令,只有超过半数后才会返回(不建议使用)
缺点:
分布式锁框架,只有等大部分的master节点数据同步完成才会返回
连接池预热:当系统刚启动时,就有大量的并发过来,这时连接池里面没有连接,那么就会导致性能问题。可以在启动的时候调用ping()命令,来进行预热。
**LRU算法:**最近最少使用。如果一个数据在最近一段时间没有被用到,那么将来被使用到的可能性也很小,所以就可以被淘汰掉;Redis中LRU算法是每次随机出5个key,淘汰掉最少使用的key,redis增加了一个24bit的字段,用来存放最后一次被访问的时间
**Redis3.0 LRU算法:**会维护一个候选池(大小为16),池中根据数据的访问时间进行排序,第一次随机选取的key都会放入池中,随后每次选取的key只有在访问时间小于池中最小的时间才会放入池中,直到放满。当放满后,如果新的key需要放入,则将池中最后访问时间最大的移除
**LRU缺点:**LRU是根据最近访问时间来进行数据淘汰,就容易导致,某个数据很久没有被访问,但是突然被访问了一次,那么Redis就会认为他是热点数据,就不会淘汰。
Redis4.0 LFU算法:根据key最近被访问频率进行淘汰,很少被访问的优先被淘汰
一个大型的位数组和几个不一样的无偏hash函数,无偏就是能够把元素的hash值算的比较均匀。会进行很多的hash运算,然后对hash值跟数组的长度进行取模。如果存在大量的不存在的key,可以使用布隆过滤器(非常的节省空间)
适用场景:数据命中不高,数据相对固定,实时性低(通常是数据较大)的应用场景,代码维护较为复杂,但是缓存空间占用很少
可以采用队列来保证读操作和写操作的顺序执行。
如果遍历只包含了Integer值的set集合,或者符合ziplists类型编码的hash或者Sset集合(说明这些集合里面的元素占用的空间足够小)那么scan会返回所有元素,直接忽略count