redis 数据存储格式
string、hash、list、set、zset(有序的set)
String:以key-value方式存储,存储多个值HSET user1:name zs user1:age 20
hash:在string基础上多了filed属性,相比String更适合同类数据归类整合,但是过期功能是能在key上,不能具体到filed
如 HMSET user1 name zs age 20 设置user1的name和age属性
list:类似队列,可以从左边或右边对数据进行操作,可以很方便的实现栈、队列等数据结构
set:存储的集合数据可以进行交集、并集、差集、取随机等操作,常用于关注模型、抽奖等
zset:相对于set多了一个score属性,可以用score这个属性进行排序,常用于热点排序
ZADD name1 1 zs 2 ls 给name1添加了score为1的zs和score为2的ls
更多操作命令见附件:链接:https://pan.baidu.com/s/1ZDQI1nTd-NHWsuRAAmfcig?pwd=fnh0
redis的单线程:
Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
redis单线程如何处理多个并发客户端:redis使用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到 文件事件分派器,事件分派器将事件分发给事件处理器,事件处理器也是单线程一次对事件进行处理;
Redis的持久化(RDB和AOF):
RDB:根据redis.conf的配置(save命令行)设置持久化的条件,触发其中一个条件就将所有内存数据持久化到dump.rdb(二进制)文件,后面生成的文件会将前面的文件覆盖;也可以通过save命令手动触发,触发的命令有save和bgsave,save命令是同步的(持久化期间redis不允许读操作,影响用户使用),bgsave是异步的(使用写时复制机制,持久化时有其他的线程写入数据则将新写入的数据生成一个副本持久化到文件中,也是默认的);
RDB持久化触发条件如下,意思是900秒之内有1条更新……,可以配置多个,满足一个条件即可;
AOF:AOF是增量覆盖,将新增的命令持久化到 appendonly.aof(redis.conf配置的默认文件名) 中,持久化策略通过appendfsync配置,如下图(always每次更新都写入文件、everysec每秒钟持久化一次、no从不持久化);AOF的文件格式如下,*num 表示一个命令的开始、num表示一个命令有几个字符串,$表示字符串的长度,红色命令标识的标识 set tuling 888;
AOF的重写:有些命令是可以优化的,比如一个数据自增多次就会产生很多无效的命令,重写的目的是优化这些无效的命令,比如将自增的命令直接使用set赋值即可;如下第三张图是配置重写的策略,达到64M的100%即重写;
混合策略(RDB和AOF的混合使用):
1、此时必须先开启AOF,然后配置 aof‐use‐rdb‐preamble yes,在重写的时候是持久化的二进制文件,后面新增的数据是aof的命令格式,这些数据都是写在aof的文件中(前面一部分是二进制,后面是aof的命令行格式);
2、提出混合策略的目的是RDB文件同步到内存中的速度快、但是容易丢数据,AOF安全性高但是同步到内存中速度慢(需要依次读取命令行并执行),混合策略既保证了安全性又有很高的速度;
3、如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
4、是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重启效率大幅得到提升;
5、所以使用混合策略时生成的备份文件上面部分是 RDB的二进制文件,下面一部门是持久化过程中新增的写命令(以AOF命令行的方式存储)
数据备份策略:定期将持久化文件拷贝到其他地方存着,如果系统或磁盘损坏将备份的文件拷到redis的目录下,重启redis就会自动将持久化的文件同步到缓存中;
redis日志设置:
redis.conf中有个logfile配置,默认是空的也就是没有日志,可以进行配置后查看redis日志 包括下面的主从及哨兵是否连上、连不上的原因;
主从和哨兵模式:
从节点配置
1、从节点和哨兵也都是redis服务,从节点只需要在redis.conf中加入以下配置即可: replicaof 192.168.60.152 6379 #在从节点中配置主节点,Redis5.0之前使用slaveof
replica‐read‐only yes # 配置从节点只读
注释掉主节点中的 bind 127.0.0.1,否则从节点读不到主节点数据(配置文件中有注释和没注释的这段命令,务必要注释)
2、通过info命令可以查看服务的主从结构,启动redis后如果从节点连不上主节点需要检查redis端口时候被防火墙拦截了(可以通过telnet查看),用以下命令可以放开防火墙端口
开放端口:firewall-cmd --add-port=6379/tcp --permanent
重载入添加的端口:firewall-cmd --reload
哨兵节点配置
1、在哨兵服务的 sentinel.conf中配置主节点,mymaster这个名字随便取,客户端访问时会用到;后面的2根据需要调整,意思是有多少台哨兵服务认为主节点挂了就进行重新选举,一般需要超过半数(哨兵服务数量/2 +1)
sentinel monitor mymaster 192.168.0.60 6379 2
当主节点挂了这个配置会自动选举生成新的主节点
2、启动哨兵服务:src/redis-sentinel sentinel.conf,进入哨兵服务:src/redis-cli -p 26379,
info命令查看主从节点(slaves从节点数量、sentinels哨兵数量)
sentinel.conf文件实时更新(只显示从节点信息)
redis常用配置及命令:
配置
daemonize yes #配置后台启动,默认是no(不是后台启动)
protected-mode no #关闭保护模式,开启的话,只有本机才可以访问redis
命令
启动redis src/redis-server redis.conf
进入redis src/redis-cli
查看redis进程 ps -ef | grep redis
关闭redis kill 进程号
配置哨兵后我们再访问redis就要访问哨兵的redis服务了,由哨兵来分发请求到主从redis服务,哨兵的sentinel.conf文件的最后可以看到从节点及哨兵信息, 当主从节点状态变化时这些配置文件实时更新;
详细课件见附件01和02:链接:https://pan.baidu.com/s/1-HQdi5exXHr2vYDiXt72iQ?pwd=fj7j
缓存击穿:大批缓存同一时间过期,大量请求穿透缓存直达数据库
解决:批量增加缓存时将这一批数据的缓存过期时间设置为一个时间段内的不同时间
比如设置24小时增加一个30分钟内的随机时间
缓存穿透:同一时间大量数据查询redis,redis中没有,击穿redis-->查询数据库也没查到
解决:数据库中查不到则在redis中存入一条空数据
血崩:缓存雪崩指的是redis缓存支撑不住或宕掉后,流量疯狂打向后端存储层,造成存储层也会级联宕机的情况
预防和解决缓存雪崩问题, 可以从以下三个方面进行着手
1) 保证缓存层服务高可用性,比如使用Redis Sentinel(主从)或Redis Cluster(集群)。
缓存双写不一致:a查询后放缓存,b更新放缓存,a查询后还没放缓存 此时 b更新放了缓存,然后a再放缓存
1、使用阿里开源的canal配合MQ解决,逻辑:mysql开启binlog日志,Canal服务端订阅Mysql binlog日志并推送到MQ消息队列,MQ收到数据后将数据更新到redis;
参考:Redis缓存与数据库双写一致性解决方案_八五年的湘哥的博客-CSDN博客_双写一致性解决方案
Redis关注模型:
为每个用户定义一个set,存储该用户关注的用户集合,集合存储用户的唯一标识id,有了用户的关注人信息后可以做以下几个操作:
-
相互关注:用集合里自己关注的人的id,去查找该用户的关注人集合,看自己是否在集合中,如果在里面,说明自己关注的人也关注了自己。
-
我关注的人也关注了他: 用自己关注的人的集合,跟自己关注的人关注的集合做交集,那么就能计算出自己关注的人跟自己都共同关注了谁。
-
查找可能认识的人:可能认识的人首先要有一个规则,怎么才算可能认识的人,暂定,自己关注的人里面,有两个人以上共同关注了某个人,就认为算是可能认识的人吧。按这个规则来设计的话:遍历自己关注的人列表后,用数学上的组合方式,分别对每个人的关注列表做交集,其结果就是自己可能认识的人。
简而言之:redis的交集,并集,差集的结合使用
redis设置值之后的返回值,如果设置失败一般会抛异常: