java总结 -- 7.redis知识记录

1 篇文章 0 订阅

一、redis数据结构,五中基本类型:

1.String:应用场景,共享session,分布式锁,计数器,限流

2.Hash:应用场景:缓存用户信息

3.List:应用场景:消息队列,文章列表

4.Set:应用场景:用户标签,生产随机数抽奖,社交需求

5.Zset:应用场景:排行榜,社交需求(如点赞)

三种特殊数据结构:

Geospatial:地理位置定位,存储地理位置

Hyperloglog:基数统计算法的数据结构,如统计网站UV

Bitmap:以比特位为单位的数组

二、缓存穿透,缓存雪崩,缓存击穿

1.缓存穿透:

查询一个一定不存的数据,由于缓存中不存在则查询数据库,查不到数据又不会写入缓存,导致每次查不到都去查数据库,增加数据库的压力。

解决方法:布隆过滤器,bloom类似一个hash set,用来判断某个元素(key)是否存在某个集合中,集合的初始位值是0,。不同的是,bloom算法不存储key的值,对于每个key的hash后的散列值,如果存在就将集合中对应的索引值由0置为1。

bloom算法的步骤:

1.首先需要n个hash函数,每个函数可以把key散列成一个整数

2.初始化一个m比特位的数组,每个比特位初始化为0

3.某个key加入集合时,用n个hash函数计算出n个散列值,并把数组中对应的比特位置为1

4.查询数组中对应的比特位,如果是1,认为存在于集合中。

优点:不需要存储key,节省空间;

缺点:容易出现误判,导致无法删除,所以要进过多次hash。

2.缓存雪崩:

数据批量过期,查询数据量巨大,请求直接到数据库,引起数据库压力过大或者down机。

解决办法:均匀设置过期时间;redis高可用

3.缓存击穿:

热点key过期,恰好这个时间点对热点key有大量的查询操作,从而直接到数据库。可以任务缓存击穿是雪崩的一个子集。缓存是请求直接到db层,雪崩是指数据库压力大或down机。

解决办法:缓存有效期永不过期;缓存失效时,不立即请求db,而是使用某些带有成功返回原子操作的命令,比如Redis的setnx,成功的时候去同步或者异步查询数据库和设置缓存,否则重试缓存获取。

三、过期策略和内存淘汰策略

1.过期策略:定时过期、惰性过期、定期过期,redis采取的是惰性过期和定期过期策略。

2.内存淘汰策略:为了解决过期策略带来的内存不足,保证redis服务不挂掉。以下八种:

volatile-lru:当内存不足纳入新数据时,从设置的过期key中,使用最近最少使用算法进行淘汰;

allkeys-lru:当内存不足纳入新数据时,从所有key中,使用最近最少使用算法进行淘汰;

volatile-lfu:当内存不足纳入新数据时,从设置的过期key中,使用最少使用频率算法进行淘汰;

allkeys-lfu:当内存不足纳入新数据时,从所有key中,使用最少使用频率算法进行淘汰;

volatile-random:当内存不足纳入新数据时,从设置的过期key中,使用随机数算法进行淘汰;

allkeys-random:当内存不足纳入新数据时,从所有key中,使用随机数算法进行淘汰;

volatile-ttl:当内存不足纳入新数据时,从设置的过期key中,根据过期时间进行淘汰,越早过期的越早淘汰;

noeviction:默认策略,当内存不足纳入新数据时,新写入的操作报错

四、redis的应用场景

缓存

共享session(用户信息)

分布式锁(setnx)

限流、排行榜(score属性)

消息队列(pubsub)

计数器应用

社交网络(点赞等操作,未使用过)

位操作(未使用过)

五、redis持久化

AOF:采用日志的形式记录每个操作,追加到文件中,重启的时候重新执行AOF文件中的命令来恢复数据,主要是解决数据持久化的实时性问题,默认是不开启的。

  • 优点:数据一致性和完整性更高,
  • 缺点:AOF记录的内容越多,文件越大,恢复数据越慢

RDB:把内存数据以快照的形式保存到磁盘上,在指定的时间间隔内,执行指定次数的写操作,将内存中的数据集快照写入磁盘中。是redis默认的持久化方式。执行完操作后,会在指定文件下生产一个dump.rdb文件,redis重启的时候通知加载dump.rdb文件来恢复数据。rdb机制可以手动触发和自动触发,手动触发分为同步和异步。

  • 场景:适合大规模的数据恢复场景,如备份,全量复制。
  • 缺点:无法做到实时/秒级的持久化

六、redis高可用

主从模式(不推荐):主节点负责读写,从节点负责读,从节点的数据来自主节点,实现原理是主从复制机制。

复制包括全量复制和增量复制。当slave第一次启动进行全量复制,流程图:

后续如果master数据发生变更,则进行增量复制,触发replicationFeedSlaves()函数,流程图:

哨兵模式:

基于主从模式实现的读写分离,还可以自动切换主从节点,系统可用性高,但是每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。

集群模式:

Redis3.0加入的,实现了Redis的分布式存储,对数据进行分片,每台redis节点上存储不同的内容。解决在线扩容的问题。既然是分布式存储,Cluster集群模式使用的分布式算法是hash slot算法,插槽算法把整个数据库分为16384个槽,到达redis的key,经过散列,分配到其中一个槽,直接跳到对应的节点上进行存取,客户端看起来就跟操作单例redis一样

一个reids集群由多个节点组成,各个节点之间通信协议时gossip协议。各个节点直接不断交换信息,交换的信息包括节点出现故障,新节点加,主从节点变更信息,slot信息等。常用的gossip协议分为四种:ping、pong、meet、fail。

七、故障转移

redis集群通过ping/pong消息,实现故障发现。主要包括“客观下线和主观下线。

故障恢复:如果下线节点是主节点,则需要从它的从节点中选出一个替换主节点,保证高可用。

八、分布式锁

控制分布式系统中多个进程访问共享资源的一种锁的实现。秒杀下单、抢红包等业务场景都要用到分布式锁。定时任务,setnx,java中redisTemplate提供的setIfAbsent方法。

分布式锁要满足以下条件

1.互斥性。在任意时刻,只有一个客户端能持有锁。

2.不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。

3.具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。

4.解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

在删除锁的时候建议使用lua脚本实现,把删除锁的原子操作交给redis。

错误的实现方式:

// 判断加锁与解锁是不是同一个客户端
if (requestId.equals(jedis.get(lockKey))) {
    // 若在此时,这把锁突然不是这个客户端的,则会误解锁
    jedis.del(lockKey);
}

比如客户端A加锁,一段时间之后客户端A解锁,在执行jedis.del()之前,锁突然过期了,此时客户端B尝试加锁成功,然后客户端A再执行del()方法,则将客户端B的锁给解除了。

建议的实现方式;

public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

    if (RELEASE_SUCCESS.equals(result)) {
        return true;
    }
    return false;
}

Redission框架解决了分布式锁过期,业务未执行完的问题,原理是开启一个守护线程(watch dog),每个一段时间(10s)检查一下锁是否还在,存在则会延长锁key的生存时间,防止锁提前到期释放。

九、mysql与redis如何保证双写一致性

1.延时双删,操作流程:

目的是为了确保读请求结束,redis不会有脏数据。由于在第一次删除缓存的同时发生了读操作,读请求会把数据库更新前的数据缓存到redis,从而引起的脏数据问题,因此更新数据库后需要再次次删除缓存操作。

2.删除缓存重试机制

由于延时双删第二次可能删除失败,造成mysql与redis数据不一致问题,所以引入重试机制。

3.读取binlog异步删除缓存

重试机制会造成好多代码入侵,所以通过数据库的binlog来异步淘汰key。

流程如下:

 1.正常更新数据到db

2.使用ali的canal将binlog日志信息投递到mq。利用mq的ack机制,确保信息的可靠性,然后消费,异步删除缓存,保证数据库与redis的一致性

3.正常的读取缓存操作

4.如果缓存不存在请求数据库

5.更新缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值