redis是非关系内存键值对数据库,类似于HashMap;
五种数据类型:String、list、hash、set、zset
内存中数据持久化
使用复制来扩展读性能:复制到多台服务器、提高读性能和可用性
使用分区来扩展写性能(hash一致性算法):当数据量大的时候,把数据分散存入多个数据库中,减少单节点的连接压力;
特点:完全基于内存;多路I/O复用模型;
- Redis和Memcache有什么区别
- Redis的线程模型是什么?
- Redis的数据类型及应用场景?
- Redis的持久化策略有哪些?AOF和RDB各有什么优缺点?
- Redis的过期策略以及LRU算法?
- redis的主从复制原理能介绍一下么?
- redis的哨兵原理能介绍一下么?
- Redis主备切换的数据丢失问题:异步复制、集群脑裂?
- Redis哨兵的底层原理?
Redis最基本的内部原理和特点就是NIO异步的单线程工作模型。
redis高可用集群,非常稳定,才作为数据库使用,存储数据。
redis官方文档:Command reference – Redis
帮助命令,help @list help @sorted_set
1、Redis和Memcache相比
具有更多的数据结构。
Redis采用Hash结构做key-value存储,组合式的压缩,内存利用率比Memcache高;简单的key-value存储,则是Memcache内存利用率高。
Memcache没有原生的集群模式,需要依赖客户端实现往集群中分片写入数据,但Redis是原生支持cluster模式的。
2、数据类型及使用场景
String
单值缓存
对象缓存:json格式数据、MSET批量设置
分布式锁:SETNX 1代表获取锁成功,DEL
计数器 INCR
Web集群session共享
分布式系统全局序列号,批量生成
Hash (双重key)
购物车
添加商品:hset cart:1001 10088 1
增加商品数量:hincrby cart:1001 10088 1
商品总数:hlen cart:1001
获得购物车所有商品:hgetall cart:1001
删除商品:hdel cart:1001
List
栈:先进后出 LPUSH + LPOP
队列:先进先出 LPUSH + RPOP
阻塞队列:Blocking MQ:LPUSH + BRPOP
LRANGE KEY
Set
新增:SADD key member ...
删除:SREM key
查出所有用户:SMEMBERS key
随机选择几个用户,SRANDMEMBER KEY 3,选择后元素还在
随机抽取几个用户,SPOP key 3,抽取后元素不在set中
集合操作:交集 SINTER set1 set 并集 SUNION set1 set2 差集 SDIFF set1 set2 set3
抽奖、点赞
zSet(sorted_set)
ZADD key score member [...]
点击新闻: ZINCRBY hot:new 1 守护
正序拿:ZRANGE key 0 9 WITHSCORES,排行版取前10条带分值
ZUNIONSTORE key 数量 具体集合 七天之内新闻总分值集合排行
3、简述Redis的过期策略和内存淘汰机制
定期删除+惰性删除:
定期删除,redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查,过期了就删除
惰性删除,获取key的时候,如果key过期,则删除,弥补了定期抽样删除的遗漏
内存淘汰机制:1、写入报错;2、随机删除(random);3、allkeys-lru:移除最少使用的key(常用),volatile-lru:设置过期时间的key,移除最少使用
4、介绍一下redis的主从复制原理
5、redis单线程模型
Redis的单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成,Redis对外提供键值存储服务的主要流程。但Redis的其他功能,持久化、异步删除、集群数据同步等,都是由额外的线程执行的。
Redis块,因为它所有的数据都在内存中,运算都是内存级别的运算。
Redis的IO多路复用,处理多客户端连接:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
高级命令
scan cursor key count num cursor:游标 类似于hash表中桶的值
6、缓存穿透、缓存击穿、缓存雪崩
缓存穿透:key对应的数据在数据源不存在,每次都会请求到数据库
解决方案:两种1、布隆过滤器,将所有的可能存在的数据哈希到一个足够大的bitmap中,不存在的数据会被这个bitmap拦截掉;2、不论数据是否存在,任然把这个空的结果缓存下来,设置比较短的过期时间,5分钟;
缓存击穿:key过期(一个key),大量的并发请求过来,从DB加载数据并回设到缓存
解决方案:使用互斥锁(mutex key),缓存失效后,从DB加载数据操作加锁,保证只有一个请求从DB加载数据,SETNX,其他的重试整个获取缓存的方法;热点数据永不过期,异步更新缓存。
缓存雪崩:大量缓存集中在某一个时间段失效,(多个key)
解决方案:缓存过期时间添加一个随机值,防止同一时间大量缓存数据过期;热点数据永不过期;分布式缓存数据库,热点数据均匀分布;
7、redis跳表 vs MySQL的B+Tree
跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问队尾目的。跳跃表的效率可以和平衡树相媲美,且实现简单。
使用场景:实现有序集合键、集群节点中用作内部数据结构;
跳跃表的level层级完全是随机的,一般来说,层级越多,访问节点的速度越快。
跳跃表数据结构如下:
B+Tree数据结构如下
此网址可以图形化查看各种数据结构
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
集群脑裂:
什么是redis的集群脑裂?
由于网络问题,导致redis master节点跟redis的slave节点和sentinel集群处在不同的网络分区,由于sentinel集群无法感知到master的存在,将slave节点提升为master,此时存在两个不同的master节点;如果原来的客户端还在基于原来的master节点继续写入数据,那么新的master节点无法同步这些数据,当网络问题解决后,sentinel集群将原来的master节点降为slave,此时再从新的master中同步数据,将会造成大量的数据丢失。
如何解决?
redis的配置文件中,有两个参数
#至少要求3个slave,完成数据通过,才认为数据写入成功
min-slaves-to-write 3
#配置复制和不同延迟不能超过10秒
min-slaves-max-lag 10
第一个参数表示连接到master的最少slave数量
第二个参数表示slave连接到master的最大延迟时间
按照上面的配置,至少要求能给3个slave节点发送数据,且slave超过10秒没有给master发送ack消息,则master就会拒绝写请求。配置了这两个参数之后,如果发生集群脑裂,原先的master节点接收到客户端的写入请求会拒绝,就可以减少数据同步之后的数据丢失。脑裂场景下,最多丢失了10秒的数据。
新版本参数变化为:
#至少要求3个slave,完成数据通过,才认为数据写入成功
min-replicas-to-write 3
#配置复制和不同延迟不能超过10秒
min-replicas-max-lag 10
此处两个参数也可以解决redis主从异步复制情况下的数据丢失问题。