Redis学习总结

1、Redis的数据类型

redis中常用的五种数据结构:string、list、set、zset、hash。

String结构底层是一个简单动态字符串,支持扩容,存储字符串。

list存储线性有序且可重复的元素,底层数据结构可以是双向链表/压缩列表。

set存储不可重复的元素,一般用于求交集、差集等,底层数据结构可以是hash和整数数组。

zset存储的是有序不可重复的元素,zset为每个元素添加了一个score属性作为排序依据,底层数据结构可以是ziplist和跳表。

hash类型存储的是键值对,底层数据结构是ziplist和hash。

redis会在性能以及节省内存间考虑,选择最适合当前状态的底层数据结构实现

list(有序可重)的底层数据结构是双向链表/压缩列表 set(不可重)=hash+整数数组, zset(有序不重)=ziplist+跳表 hash(存键值对)=ziplist+hashtable

2、Redis为什么这么快?

1)基于内存(因为 Redis 是基于内存的操作,CPU 不会成为 Redis 的瓶颈);

2)单线程减少上下文切换,同时保证原子性;

3)IO多路复用;

4)高级数据结构

3、我对Redis的了解

Redis是一款基于键值对的NoSQL数据库,与其他键值对数据库不同的是,Redis中拥有string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、 HyperLogLog、GEO(地理信息定位)等多种数据结构,这给Redis带来了满足多种应用场景的能力,而且,Redis将所有数据放到内存中的做法让它的读写性能十分惊人。不仅如此,Redis的持久化机制保证了在发生类似断电,机械故障等情况时,内存中的数据不会丢失。此外Redis还提供了键过期、发布订阅、事务、流水线、Lua脚本等多个附加功能。总之,在合适的情况下使用Redis会大大增强系统的性能,减少开发人员工作量。

4、什么是乐观锁?

乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去那数据的时候都认为别人不会修改,所以 不会上锁,但是在修改的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机 制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。redis就是使用这种check-and-set机制实现 事务的。

5、什么是悲观锁?

悲观锁(Pessimistic Lock),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每 次在拿数据的时候都会上锁,这样别人拿到这个数据就会block直到它拿到锁。传统的关系型数据库里面 就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁。

6、redis事务三特性

(1)单独的隔离操作 事务中的所有命令都会序列化、按顺序地执行,事务在执行过程中,不会被其他客户端发送来的命令请 求所打断。

(2)没有隔离级别的概念 队列中的命令没有提交(exec)之前,都不会实际被执行,因为事务提交前任何指令都不会被实际执 行。

(3)不能保证原子性 事务中如果有一条命令执行失败,后续的命令仍然会被执行,没有回滚。 如果在组队阶段,有1个失败了,后面都不会成功;如果在组队阶段成功了,在执行阶段有那个命令失败 就这条失败,其他的命令则正常执行,不保证都成功或都失败。

7、Redis持久化之RDB

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是键快 照文件直接读到内存里。

8、Redis持久化之AOF

以日志的形式来记录每个写操作(增量保存),将redis执行过的所有写指令记录下来(读操作不记 录),只允追加文件但不可改写文件,redis启动之初会读取该文件重新构造数据,换言之,redis重启 的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

9、Redis主从复制

主机更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为 主。

10、Redis哨兵模式

反客为主的自动版,能够自动监控master是否发生故障,如果故障了会根据投票数从slave中挑选一个 作为master,其他的slave会自动转向同步新的master,实现故障自动转义。

11、Redis集群

redis集群是对redis的水平扩容,即启动N个redis节点,将整个数据分布存储在这个N个节点中,每个节 点存储总数据的1/N。

12、Redis缓存穿透

当系统中引入redis缓存后,一个请求进来后,会先从redis缓存中查询,缓存有就直接返回,缓存中没有就去db中查询,db中如果有就会将其丢到缓存中,但是有些key对应更多数据在db中并不存在,每次针对此次key的请求从缓存中取不到,请求都会压到db,从而可能压垮db。 比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用大量此类攻击可能 压垮数据库。

解决方案:

(1)对空值缓存 如果一个查询返回的数据为空(不管数据库是否存在),我们仍然把这个结果(null)进行缓存,给其 设置一个很短的过期时间,最长不超过五分钟

(2)设置可访问的名单(白名单) 使用redis中的bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次范文和 bitmap里面的id进行比较,如果访问的id不在bitmaps里面,则进行拦截,不允许访问

(3)采用布隆过滤器 布隆过滤器可以用于检测一个元素是否在一个集合中,它的优点是空间效率和查询的速度都远远超过一 般的算法,缺点是有一定的误识别率和删除困难。

(4)进行实时监控 当发现redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名 单限制对其提供服务(比如:IP黑名单)

13、Redis缓存击穿

redis中某个不存在的key或者热点key(访问量很高的key)过期,此时大量请求同时过来,发现缓存中没有命中,这些请 求都打到db上了,导致db压力瞬时大增,可能会打垮db,这种情况成为缓存击穿。

解决方案:

key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据,这个时候,要考虑一个问题:缓 存被“击穿”的问题,常见的解决方案如下:

(1)预先设置热门数据,适时调整过期时间 在redis高峰之前,把一些热门数据提前存入到redis里面,对缓存中的这些热门数据进行监控,实时调 整过期时间。

(2)使用锁 缓存中拿不到数据的时候,此时不是立即去db中查询,而是去获取分布式锁(比如redis中的setnx), 拿到锁再去db中load数据;没有拿到锁的线程休眠一段时间再重试整个获取数据的方法。

14、Redis缓存雪崩

key对应的数据存在,但是极短时间内有大量的key集中过期,此时若有大量的并发请求过来,发现缓存 没有数据,大量的请求就会落到db上去加载数据,会将db击垮,导致服务奔溃。

缓存雪崩与缓存击穿的区别在于:前者是大量的key集中过期,而后者是某个热点key过期。

解决方案:

缓存失效时的雪崩效益对底层系统的冲击非常可怕,常见的解决方案如下:

(1)构建多级缓存 nginx缓存+redis缓存+其他缓存(ehcache等)

(2)使用锁或队列 用加锁或者队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发 请求落到底层存储系统上,不适用高并发情况。

(3)监控缓存过期,提前更新 监控缓存,发下缓存快过期了,提前对缓存进行更新。

(4)将缓存失效时间分散开 比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样缓存的过期时间重复率 就会降低,就很难引发集体失效的事件。

15、分布式锁

随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多 进程且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提 供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分 布式锁要解决的问题。

16、redis缓存更新策略

1、内存淘汰:不用自己维护, 利用Redis 的内存淘汰机制, 当内存不足时自动淘汰部分数据。下次查询时更新缓存。

2、超时剔除:给缓存数据添加TTL 时间, 到期后自动删除缓存。下次查询时更新缓存。

3、主动更新:编写业务逻辑, 在修改数据库的同时, 更新缓存。

17、先删缓存还是后删除缓存?

无论先删缓存还是后删除缓存都可能

17.1 先删除缓存

1、如果先删除Redis缓存数据,然而还没有来得及写入MySQL,另一个线程就来读取。 2、这个时候发现缓存为空,则去Mysql数据库中读取旧数据写入缓存,此时缓存中为脏数据。 3、然后数据库更新后发现Redis和Mysql出现了数据不一致的问题。

17.2 后删除缓存

1、如果先写了库,然后再删除缓存,不幸的写库的线程挂了,导致了缓存没有删除。 2、这个时候就会直接读取旧缓存,最终也导致了数据不一致情况。 3、因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题造成数据库的不一致。

解决方案延时双删策略

1、先删除缓存 2、再写数据库 3、休眠xxx毫秒(根据具体的业务时间来定) 4、再次删除缓存

为什么双删?

因为第一次删除的是还没更新前的数据,第二次删除则是因为读取的并发性导致的缓存重新写入数据出现的垃圾数据。

18.redis分布式会话实现session共享

问题描述:

在分布式项目中有多个服务器,各个服务器存储的token信息不共享;

解决方案:

1、将token存储到redis中,若服务器需要获取token,直接在redis中取即可,实现分布式通信。

2、每次读取到token信息时,延长token的过期时间可以避免用户在登录几分钟后token过期导致需要重新登录的情况。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值