redis的一些知识点

redis:
缓存还可以实现 熔断机制:当存储层挂掉了,可以将
请求打在缓存上,保证系统的
运行。
特点:数据类型丰富
支持数据磁盘持久化存储
支持主从
支持分片
为什么Redis能这么快?
100000+QPS(QPS即query per second,每秒内查询的次数)
1.完全基于内存,绝大部分请求是纯粹的内存操作,执行效率搞
2.采用单线程,单线程也能处理高并发请求,像多核也可以启动多实例
(这里的单线程,是只在处理网络请求的时候,是单线程的)
3.数据结构简单,对数据操作也简单 类似HashMap,查找,操作都是 O(1)
4.使用多路I/O复用模型,非阻塞IO
多路I/O复用模型
FD: File Descriptor, 文件描述符
一个打开的文件用过唯一的描述符进行引用,该描述符
是打开文件的元数据到文件本身的映射。
select 系统调用(NIO)
Redis采用的I/O多路复用函数:epoll/kqueue/evport/select
1.根据操作系统不用选择不用的函数
2.优先选择时间复杂度为O(1)的I/O多路复用函数作为底层实现
3.以时间复杂度为O(n)的select作为保底
4.react设计模式监听I/O事件
说说你用过的Redis的数据类型
String; 使用:set name "redis"incr UserId 自增1
Hash:使用:hmset lilei name "LiLei" age 26; hget lilei age; hset lilei age 28
List:使用: lpush mylist aaa; lrang mylist 0 10(从左到右取出 0-10个数),lpop
Set:使用:sadd myset 1111; smembers myset;
Sorted Set: 使用: zadd myzset 3 abc (这里的3,是大小排序);zrangebyscore myzet 0 10
集合有求交集,并集的操作
高级:HyperLogLog,用于支持存储地理位置信息的Geo

使用keys对线上的业务的影响
KEYS pattern:查找所有符合给定模式pattern的key
A.KEYS指令一次性返回所有匹配的KEY
B.键的数据量过大会使服务卡顿
SCAN cursor [MATCH pattern] [COUNT count]
A.基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程
B.以0作为游标(cursor)开始一次新的迭代,直到命令返回游标0完成一次遍历
C.不保证每次执行都返回某个给定数量的元素,支持模糊查询
D.一次返回的数量不可控,只能是大概率符合count参数

从海量Key里查询出某一固定前缀的Key
命令:dbsize(redis中的key的数量)
keys k1*(找出以k1开头的key)
(若数据量过大,会使卡住)
命令:scan 0(游标) match k1*(条件) count 10 (返回10条)
scan 0 match k1* count 10
返回值:1) “3213213213” (游标,当前访问到的位置)
2) 1)“k1432432”
2)"k1798879"
3)"k1789789"(返回结果,不一定是10个)

scan 3213213213 match k1* count 10
可能会获取到重复的数据,剩下的就要在代码曾进行控制了

如何通过redis实现分布式锁
分布式锁需要解决的问题
1.互斥性
2.安全性
3.死锁
4.容错
命令:SETNX key value:如果key不存在,则创建并赋值
时间复杂度:O(1)
返回值:设置成功,返回1;设置失败,返回0
若key 存在 则返回0(即失败)

如何解决setnx长期有效的问题
EXPIRE key seconds
设置key的生存时间,当key过期时(生存时间为0),会被自动删除
缺点:不是原子性操作

在代码中这样使用:
RedisService redisService = SpringUtils.getBean(RedisService.class);
long status = redisService.setnx(key,"1");
if(status == 1 ){
//设置过期时间
redisService.expire(key,expire);
//执行独占资源逻辑
something();
}
对上面方案的一个改进,
SET key value [EX seconds] [PX milliseconds] [NX|XX]
EX second:设置键的过期时间为second秒
PX millisecond:设置键的过期时间为millisecond毫秒
NX 只在键不存在时,才对键进行设置操作
XX 只在键已存在时,才对键进行设置操作
SET操作成功完成时,返回OK,否则返回nil

可以将 value 设置成requestID,threadId,来标识被哪个占用了
伪代码:
RedisService redisService = SpringUtils.getBean(RedisService.class);
String result = redisService.set(lockKey,threadId,SET_IF_NOT_EXIST,....,NX);

if("OK".equals(result)){
//执行独占资源逻辑
something();
}


大量的key同时过期的注意事项
集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象
解决方案:
在设置key的过期时间的时候,给每个key加上随机值

如何使用Redis做异步队列
使用List作为队列,RPUSH生产消息,LPOP消费消息
缺点:没有等待队列里有值就直接消费
弥补:可以通过在应用层引入sleep机制去调用lpop重试
方法2:
BLPOP key [key ...] timeout:阻塞直到队列有消息或者超时
缺点:只能提供一个消费者消费

方法3:
pub/sub:主题订阅者模式
pub:发布者publish myTopic"hello"
sub:订阅者subscribemyTopic
缺点:消息的发布是无状态的,无法保证可达


Redis如何做持久化
方法一:
RDB(快照)持久化:保存某个时间点的全量数据快照
配置:redis.confvim redis.conf/save(查找)
快照策略;
save 900 1900秒内有1条记录写入,就保存
禁用rdb :
save ""

dump.rdb 就是数据保存的文件
手动:
save:阻塞Redis的服务器进程,直到RDB文件被创建完成
bgsave:Fork出一个子进程来创建RDB文件,不阻塞服务器进程
lastsave 上次执行save指令的时间

可以使用代码隔一段时间调用bgsave,备份一下
然后修改备份名称
mv dump.rdbdumpXXXXX.rdb

自动化出发RDB持久化的方式
根据redis.conf配置里的save m n 定时触发(用的是bgsave)
主从复制时,主节点自动触发
执行Debug reload
执行shutdown且没有开启AOF持久化

copy-on-write 读共享

缺点;
内存数据的全量同步,数据量大于I/O而严重影响性能
可能会因为redis挂掉而丢失从当前至最近一次快照期间的数据

方法二:
AOF(Append-Only-File)持久化:保存写状态
1.记录下除了查询以外的所有变更数据库状态的指令
2.以append的形式追加保存到AOF文件(增量)
默认关闭
需要修改 redis.conf 中appendonly no/yes
或者使用命令:config set appendonly yes
随着新增、修改命令不断增加,aof文件大小不断增加
日志重写解决AOF文件大小不断增加大小的问题
bgrewrite ,会触发,整合命令
redis启动时,如果有aof文件,就加载aof文件
没有的话,就加载rdb文件

RDB 和 AOF 的优缺点
RDB优点:全量数据快照,文件小,恢复快
RDB缺点:无法保存最近一次快照之后的数据
AOF优点;可读性高,适合保存增量数据,数据不易丢失
AOF缺点:文件体积大,恢复时间长
RDB-AOF混合持久化方式4.0开始支持
AOF 前半段 是RDB的全量数据,后半段是redis对数据的操作
使用 BGSAVE 做镜像全量持久化,AOF做增量持久化
redis 重启是先加载rdb的数据,重构,再用aof 重现近期操作的命令

使用Pipeline的好处
pipeline 和 linux 的管道类似
redis基于请求/响应模型,单个请求处理需要一一应答
(若命令过多,会增大系统网络I/O的调用)
pipeline批量执行指令,节省多次IO往返的时间
(指令最好是互相没有依赖的)
有顺序依赖的指令建议分批发送
redis的同步机制
主从(写在主节点,读在从节点),
缺点:(主机节点挂了后,就不能进行写操作了)
redis Sentinel (分布式系统)
解决主从同步master宕机后,主从切换问题,
监控:检查主从服务器是否运行正常
提醒:通过API向管理员或者其他应用程序发送故障通知
自动故障迁移:主从切换
哨兵:
redis 集群
redis 集群原理:
一致性哈希算法:对2^32取摸,将哈希值空间组织成虚拟的圆环。
0 --2^32-1
【redis的一些知识点】
如何从海量数据里快速找到所需?
分片:
按照某种规则去划分数据,分散存储在多个节点上

    推荐阅读