一、reids为何这么快,底层原理
1、redis主要在内存上操作,单线程
2、采用了I/O多路复用,调用底层的epoll/kqueue/evport函数,复杂度是O(1)级别的,用select函数兜底,复杂度是O(1)
redis多路复用原理
单个线程(文件事件分配器)管理多个I/O流,将到达的I/O流放置到队列当中,然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中
二、redis的数据结构以及底层实现
redis的数据结构主要包括String,hash,list,set,sorted set
sorted set的底仓数据结构
采用了链表,跳跃表
三、如何从海量数据当中查询固定前缀的key
keys命令会阻塞redis,可以采用scan命令,不断的迭代查询,scan 0 hon* count 10,其中count不一定会返回具体数量的结果,比如10,有可能返回4条数据
四、redis如何实现分布式锁
分布式锁需要解决的问题: 1、互斥性 2、安全性(获得锁只能由自己销毁) 3、死锁 4、容错
如何解决SETNX长期有效的问题
-
setnx key value redis当中有个命令叫setnx key value,操作是原子性的,如果不存在就创建赋值,时间复杂度为O(1),成功返回1,失败返回0
-
EXPIRE key seconds 设置key的生存时间,当key过期时,会被自动删除 组合起来的就不是原子性,实现分布式锁会存在一直独占的现象
-
SET key value [EX seconds][PX milliseconds][NX|XX] EX seconds设置过期键的时间为second秒
PX milliseconds 设置过期键的时间为xx毫秒
NX 只在键不存在时,才对键进行设置操作,相当于setnx
XX 只在键存在时,才对键进行设置操作
例如:set locktarget hello EX 10 NX
RedisService redisService = StringUtils.getBean(RedisService.class);
String result = redisService.set(lockKey, requestId, SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expireTime);
if("OK".equals(result)){
//执行独占资源
doOcuppiedWork();
}
大量的key过期的注意事项
在key的过期时间后面加个一个随机的时间值
五、如何使用redis来时间异步队列
可以采用list结构,用rpush生产消息,lpop消费消息
可以采用BLPOP key [key...] timeout 阻塞直到队列有消息,缺点是只能提供一个消费者消费
可以采用redis的发布订阅模式 pub/sub模式,缺点是消息是无状态的,无法保证消息可达
六、redis如何做持久化
RDB(快照)持久化,保存某个时间点的全量的数据快照
redis conf下面有策略
save 900 1
save 300 10
save 60 10000
### 重要配置 备份进程出错的时候,主进程就停止写入操作,保护持久化的一致性的特性
stop-writes-on-bgsave-error yes
### 压缩
rdbcompression no
rdb文件生成的两种方式
- SAVE命令:阻塞redis服务器进程,直到rdb文件创建完成
- BGSAVE命令:fork一个子进程来创建RDB文件,不阻塞服务器进程
自动化触发生成rdb持久化的方式
- 根据redis.conf里配置的SAVE m n 定时触发(采用的是bgsave)
- 主从复制时,主节点自动触发
- 执行debug reload
- 执行shutdown且没有开启AOF持久化
BGSAVE原理
RDB持久化的缺点
- 内存数据全量同步,数据量大会由于I/O而严重影响性能
- 可能因为redis挂掉而丢失从当前到最近一次快照之前的数据
AOF(Append-only-file)持久化
- 记录下除了查询以外所有变更数据库状态的指令
- 以Append的形式追加保存到AOF文件中(增量)
AOF和RDB的优缺点
- RDB优点:全量数据快照,文件小,恢复快
- RDB缺点:无法保存最近一次快照之后的数据
- AOF优点:可读性高,适合保存增量数据,数据不易丢失
- AOF缺点:文件体积大,恢复时间长
redis4.0之后采用RDB-AOF混合持久化方式,采用bgsave做镜像全量持久化,AOF做增量持久化
七、Redis同步机制
主从同步原理
master-salve 最终一致性
全同步流程
1、全量同步流程
slave发送sync命令到master,master后台启动一个线程生成rdb文件,master把在生成快照文件期间接收到的增量命令缓存起来,将rdb文件发送给slave,slave用新低RDB文件替换旧的RDB文件,master再将增量命令发送给slave
2、增量同步
master接收到了用户的命令,判断是否需要扩展到salve,写操作需要读操作就不需要,然后master将命令追加到AOF文件当中,将操作传播到其他slave中,写入缓存中,将缓存数据发送给salve
redis sentinal
解决master宕机之后主从切换问题
八、redis集群原理
- 核心思路:将key分散到各个节点上
一致性hash算法
在2的32次方的圆环上映射,如果服务器少会有hash环的数据倾斜的问题,引入虚拟节点解决这个问题