Java-Redis-基础
一、Java-Redis-基础
1.1 基本数据结构
- 字符串string:1)缓存功能 2)计数器 3)共享用户Session
- 列表list:1)消息队列 2)文章列表或者数据分页展示的应用
- 字典hash
渐进式rehash - 渐进式rehash会在rehash的同时,保留新旧两个hash结构,如上图所示,查询时会同时查询两个hash结构,然后在后续的定时任务以及hash操作指令中,循序渐进的把旧字典的内容迁移到新字典中。当搬迁完成了,就会使用新的hash结构取而代之。
image.pngimage.png
- 集合set:1)去重 2)交集、并集、差集
- 有序列表zset:1)排行榜 2)带权重的队列
1.2 持久化
- RDB:RDB持久化机制,是对Redis中的数据执行周期性的持久化。RDB原理:fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
- AOF:AOF机制对每条写入命令作为日志,以 append-only的模式写入一个日志文件中,因为这个模式是只追加的方式,所以没有任何磁盘寻址的开销,所以很快,有点像Mysql中的binlog。
两种机制全部开启的时候,Redis在重启的时候会默认使用AOF去重新构建数据,因为AOF的数据是比RDB更完整的。
混合持久化:Redis 4.0 - 将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小;于是在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此大幅得到提升。
image.png1.3 哨兵Sentinel
- 集群监控:负责监控Redis master和slave进程是否正常工作。
- 消息通知:如果某个Redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
- 故障转移:如果master node挂掉了,会自动转移到slave node上。
- 配置中心:如果故障转移发生了,通知client客户端新的master地址。
1.4 主从同步
启动一台slave的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
image.png1.5 内存淘汰机制
Redis的过期策略,是有定期删除+惰性删除两种。
- noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
- allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
- volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int MAX_CACHE_SIZE;
public LRUCache(int cacheSize) {
// 容量为最大值/0.75,即最大负载容量为maxSize
// accessOrder=true 根据查询排序,即最近被使用的放到后面
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
MAX_CACHE_SIZE = cacheSize;
}
/**
* 此方法为钩子方法,map插入元素时会调用此方法
* 此方法返回true则证明删除最老的因子
*/
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
}
}
- 当新数据插入时添加到链表尾部(插入)
- 当缓存命中时,将数据移动到链表尾部(移动)
- 当链表满时,把链表头部的数据删除(淘汰)
- 为了方便查找数据,可以使用一个普通map,在map和链表节点之间做引用映射(查找)
1.6 穿透、击穿、雪崩
- 缓存穿透:缓存和数据库中都没有的数据,而用户不断发起请求。1)在接口层增加校验;2)布隆过滤器。
- 缓存击穿:指一个Key非常热点,在不停的扛着并发,并发集中对这一个点进行访问,当这个热Key在失效的瞬间,持续的并发请求就穿破缓存,直接请求数据库。
- 缓存雪崩:大面积的缓存失效。1)在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值,这样可以保证数据不会在同一时间大面积失效;2)设置热点数据永远不过期;3)数据预热 ;4)二级缓存。
1.7 Bloom Filter
布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。
Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率。
1.8 Redis线程模型
Redis线程模型:Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler)。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
1.9 高级用法
- Bitmap:位图是支持按 bit 位来存储信息,可以用来实现布隆过滤器(BloomFilter)
- HyperLogLog:供不精确的去重计数功能,比较适合用来做大规模数据的去重统计,例如统计 UV
- Geospatial:可以用来保存地理位置,并作位置距离计算或者根据半径计算位置等
- pub/sub:功能是订阅发布功能,可以用作简单的消息队列
- Lua:Redis支持提交Lua脚本来执行一系列的功能
- 事务:Redis只保证串行执行命令,并且能保证全部执行,但是执行命令失败时并不会回滚,而是会继续执行下去