redis知识点学习

基本数据结构

String:String类型的使用场景:value除了是字符串外还可以是数字!
计数器、统计多单位的数量、粉丝数、对象缓存存储
List:list列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)
Set:set类型,无序去重,应用场景:好友共同关注
Hash:hash类型,key-[field:value],应用场景:更适合于存储对象信息(变更信息),例如 hmset user:1 name “zhmsky” age 23
Zet:Zset类型,有序集合,zadd salary 21000 zhmsky,应用场景:基本排序,加权排序,排行榜

事务

redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序执行,事务在执行过程中,不会被其它客户端发送过来的命令所打断。redis事务的主要作用就是串联多个命令防止别的命令插队。

开启事务:multi命令(之后的所有命令都会进入等待队列中)
执行事务:exec命令(将等待队列中的所有命令按顺序一次性执行)
放弃事务:discard命令

redis事务不支持ACID特性,redis事务的三特性:
1、单独的隔离操作:事务中的所有命令都会被序列化、按顺序执行。事务在执行过程中不会被其它客户端发送的请求打断。
2、没有隔离级别的概念:队列中的命令没有提交之前都不会被实际执行
3、不保证原子性:事务中有一条命令执行失败,其后的命令仍然会被执行,没有回滚

事务的错误处理

  1. 在组队中某个命令出现了报告错误,执行时整个等待队列中的所有命令都被取消(命令的语法错误);
  2. 在执行过程中某个命令出现了错误,则只有报错的命令不会被执行,其它正常命令都会执行(类型不匹配)

悲观锁: 即很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,只有当自己拿到锁才具
有操作权限。(行锁,表锁,读/写锁),效率低

乐观锁:即很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断在此期间是否有人更新该数据(引入版本号 version字段),乐观锁适用于多读的应用场景。redis也就是采用这种机制来实现事务的。
可以使用watch监视器当乐观锁用:在执行multi之前,先执行watch key1 (key2),可以监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其它命令所改动,那么事务将被打断

redis持久化

RDB(Redis DataBase):在指定的时间间隔内将内存中的数据集快照(snapshot快照)写入磁盘,恢复时是将快照文件直接读到内存里;
redis会单独创建一个子进程来进行持久化,先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件成为正式RDB文件;RDB的缺点是最后一次持久化的数据可能丢失。
触发机制:
1、sava规则满足的情况下,会自动产生RDB文件;
2、执行flushall命令,也会产生RDB文件;
3、退出redis,会自动产生RDB文件

AOF(Append Only File):以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加但不可以改写文件,redis在启动之初会读取该文件重新构建数据,也就是根据日志文件内容将写指令从前到后执行一次以完成数据的恢复。

redis主从复制

是指将一台redis服务器的数据复制到其它的redis服务器。前者为主节点(master),后者为从节点(slave);数据的复制时单向的,只能由主节点到从节点,master以写为主,slave以读为主。

默认只有一台主机,SlaveOf 127.0.0.1 6379命令:从属于主机127.0.0.1的6379端口;主机可以写,从机不能写只能读!主机中的所有信息和数据都会被自动被从机保存!但是从机设置最好采用配置文件的方式(永久的),如果是用命令行的方式设置从机,当从机宕机后再恢复连接,则该从机会自动设置成主机。

复制原理

从机启动成功连接到主机后会发送一个sync命令;
主机接收到命令,启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,主机将传送整个数据文件到从机,完成一次完全同步。

全量复制:从机在接收到整个数据库文件后,将其存盘并加载到内存中;
增量复制:主机继续将新的所有收集到的修改命令依次传送给slave,完成同步;

手动选老大(主机)模式:SlaveOf no one命令可以将当前节点设置为主节点(主机)

哨兵模式(自动选主机)

redis提供哨兵(sentinel)机制,哨兵作为独立进程独立运行,其原理是 哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例。当哨兵检测到主机宕机后,会自动将从机切换成主机,然后通过发布订阅模式通知其它从机修改配置文件,让其切换成主机(可以设置多个哨兵,哨兵集群);

如果主机宕掉,哨兵自动投票选取新的主机,当原主机重新上线后,会自动重新设置为从机

redis集群

redis服务器容量不够,redis如何进行扩容? 面对大量并发写操作,redis如何分摊?
-----建立集群

集群建立方式:推荐采用无中心化集群配置。例如有3台redis服务器,每台服务器各存储用户、商品、订单信息,3台服务器之间是串行的(即其中每一台服务器都可以作为入口,从而实现类似转发的功能)

缓存穿透(查不到)

当用户查询数据时,先走redis缓存,发现缓存中没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有。当大量用户都去查询时,缓存没有命中(秒杀),于是都去请求持久层数据库,这时会给持久层数据库造成压力,此时就相当于出现了缓存穿透。

主要现象

  1. redis查询不到数据(命中率急速下降)
  2. 出现很多非正常url访问 (缓存穿透就相当于redis缓存没有起到作用)

解决办法

  1. 布隆过滤器
  2. 放置空对象(也就是当redis缓存中查询不到数据时,放置空值充当缓存,设置该空值的过期时间很短,不超过5分钟)
  3. 设置可访问名单(白名单)

缓存击穿(量太大,某一个key缓存过期)

指某一个key非常热点,在不停的扛着大并发,集中对一个点进行访问,当这个key在失效的瞬间,持续的大并发就击穿缓存,直接请求持久层数据库。导致数据库压力瞬间过大。

解决办法

  1. 预先设置热点数据,加大热点数据key的有效时间
  2. 分布式锁(例如setnx)

缓存雪崩(大量缓存key集中过期)

在某一时间段,大量缓存key集中过期失效(从而导致持久层数据库访问压力迅速增大,数据库响应变慢,请求响应变慢,引发大量请求于redis等待,使得redis服务器崩溃)或者redis宕机

解决办法

  1. 构建多级缓存架构:nginx缓存+redis缓存+其它缓存
  2. 使用锁或队列
  3. 设置过期标志更新缓存(在缓存key即将过期时,提前触发另外线程在后台更新实际key的缓存)
  4. 将缓存失效时间分散开(尽量减少同一个时间段内的缓存key的失效时间)

分布式锁(核心就是 setnx )

为什么需要分布式锁?
----随着业务发展,原来单体单机系统逐渐演化为分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同的机器上,原来的单机并发控制锁失效,为了解决这个问题,需要一种跨JVM的互斥机制来控制共享资源的访问。

用redis来实现分布式锁

  1. set key 10 nx ex 10 上锁并同时设置过期时间,解决锁一直未释放问题
  2. expire (“lock” time) del(“lock”)释放锁

可能会遇到的问题
一、误删

  1. 假设现在有三台服务器(a,b,c)要去操作某个数据,现在a先抢到锁进行操作;
  2. a抢到锁并上锁执行业务操作,但是突然服务器卡顿(此时业务功能并没有完成),但是锁因超时而自动释放;
  3. b此时抢到锁并实行业务操作,但是过了一会,a反应过来继续执行业务操作,当业务完成后,手动释放锁,此时b还没执行完,却被a把锁释放了

解决上述误删问题(使用uuid解决误删):

  1. set lock uuid nx ex 10 设置uuid来表示不同的操作
  2. if(uuid.equals(redisUtils.get(“lock”))){redisUtils.delete(“lock”)} 在释放锁的时候,判断当前操作的uuid是否等于锁的 uuid,一 样才能手动释放锁

二、缺乏原子性

  1. 假设现在有两个服务器(a,b)要去操作某个数据,现在a先抢到锁执行业务操作;
  2. 在释放锁的时候,先比较uuid,发现一样,在刚准备手动释放锁但还没释放的时候,锁超时而自动释放了;
  3. 然后b又抢到锁执行业务操作,a又手动释放锁了,又造成了误删
    解决办法:使用lua脚本来保证原子性

猜你喜欢

转载自blog.csdn.net/weixin_42194695/article/details/123012338
今日推荐