• Redis详解


    Redis详解

    什么是Redis

    Redis是一个开源的,内存数据库,它可以作为数据库、缓存和消息中间件。它支持多种类型的数据结构。如字符串string、散列hash、列表list、集合set、有序集合zset。Redsi还支持事务和不同级别的持久化操作。
    

    各种数据类型 应用场景

    # 五种数据类型
    这里的数据类型我们统一认为是值得value,因为key都是string
    ## string
    这个类型是最常用的一个类型,Redis的String类型每个key可以存储512MB的数据。不要看type为String,其实它还可以存储数字等各种java类型,甚至是序列化的对象、图片、json字符串等。
    
    通过string类型,我们可以设计出计数器、点赞、分布式锁、对象存储(序列化或者json)等。
    ## hash
    存储一个一个map,可以存在多个key-value。可以通过这个存储一些没有序列化的对象。可以实现保存用户状态,设置一个过期时间即可。
    ## list
    List是一个基本类型,根据它的lpush、rpush,等命令可以实现出队列、栈等数据结构。利用这些数据结构的特点帮我我们解决很多问题。
    ## set
    这就类似于我们java中的set,它的内容不会重复,可以关注列表等。
    ## zset
    比set多了一个排序规则,可以使用它做排行榜,它有一个top命令,可以取出前N个。
    
    # 三大特殊类型
    
    ## 坐标geospatial
    记录一组经纬度,可以方便的计算两个经纬度之间的位置,附近的人等等。
    ## 并集Hyperloglog
    可以存储2^64个元素的集合,可以很方便的计算并集
    ## 位图bitmaps
    存储二进制位0和1 可以存储多个0 1 ,结合数据字典可以实现很多业务。例如统计每周打卡天数,每月签到次数等
    

    Redis为什么是单线程 单线程还这么快?

    # 为啥是单线程的?
    因为Redsi官方说,Redis的性能瓶颈不在CPU,它对CPU的需求比较低。另外使用多线程还会涉及到很多的问题。Redis的瓶颈在网络带宽和内存大小上。
    
    # 单线程还这么快?
    1、纯内存操作
    2、非阻塞IO+多路复用机制
    3、单线程避免频繁切换上下文
    

    Redis中的事务

    # redis中的事务
    Redis事务的本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行。
    
    **redis中的单条事务是有原子性的,但是redis中的事务是不保证原子性的。**
    **redis中的事务没有隔离级别的概念,所有的命令在事务中,并没有被执行,只有发起命令时,才会被执行**
    
    ## redis的事务:
    ----- 队列 set set set 执行 -----
    - 开启事务(multi)
    - 命令入队(set key val... set key2 val2...)
    - 执行事务(exec) OR - 取消事务(discard)
    当执行exec后,事务中的操作将有序的进行。取消事务后队列中的代码都不会被执行。当事务exec或者discard后就代表此次事务执行完毕了。
    
    ## 事务何时会失败?
    当队列中存在编译时异常, 事务中所有的命令都不会执行(例如:使用了错误的命令导致redis报错)。如果出现运行时异常,除了出错部分,其他的仍然会被执行(例如:给字符串incr)。
    
    ## 乐观锁和悲观锁
    所谓悲观锁,就是认为无论什么时候都会出问题,任何操作都会加锁。所谓乐观锁就是认为任何情况都不会出问题。所有操作都不会加锁。
    但是乐观锁会在更新之前查询一下version字段的值,修改的时候判断一下在此期间是否有人修改过数据。  
    
    ## watch监控版本
    redis可以实现乐观锁,通过watch来监控。
    在redis中实现乐观锁的方法非常的简单,在事务之前加上watch key即可
    例如:
    version : 10
    watch version
    multi
    set version 11
    set key val...
    exec
    此时可以正常执行成功,
    
    但是如果在此期间,有其他线程修改了version就无法执行事务。
    

    RDB AOF

    # Redis持久化
    redis是一个内存数据库,意味着断电丢失。所以它的持久化是非常有必要的。Redis中提供了两种持久化方式,RDB和AOF。默认的配置会保存在redis的data目录中,rdb保存在dump.rdb中,aof存在appendonly.aof中
    
    ## RDB快照
    所谓RDB就是在一段时间内将内存中的数据快照写入磁盘,也就是所谓的snapshot(快照)。恢复时,从快照中将数据恢复至内存中。
    在redis的配置文件中存在如下配置
    save 900 1
    save 300 10
    save 60 100000
    也就是说,在900S内只要有一次修改操作,300秒内发生10次修改操作,60秒内发生10000此修改该做就会触发RDB操作。
    
    RDB的优势:文件保存的完整、恢复快。
    
    ## AOF日志
    每次操作都会被立即记录到磁盘中,性能差但是数据保存的十分完整。它有三种触发机制,主要是两种吧,一个是每秒保存,另一种是每次保存。优点:AOP比RDB更加可靠,一般AOF每隔一秒通过一个后台线程执行一次fsync操作,最多丢失1秒的数据。而且AOP还可以进行灾难恢复,如果不小写使用了flushall清空了所有数据,也可以通过AOF来恢复。缺点就是AOF的文件会很大。
    

    穿透 雪崩

    # 为什么要用缓存?
    当一个数据的访问量非常高频的时候,会对数据库造成巨大的压力。所以我们引入了缓存的概念,当用户需要操作DB之前,先判断缓存中是否存在,如果存在就直接从缓存拿,没有的话再查数据库,再放入缓存一份。
    那么此时如果缓存挂掉了,用户的请求都直接访问DB这将是灾难性的。
    
    # 什么是雪崩?
    内存的价格是比较昂贵的,所以缓存中的数据会根据某些策略来设置过期时间,主要是惰性删除和定期删除两种。如果缓存设置的过期时间是相同的,这段时间内会有大量的key过期,所有的请求都会跳过redis直接访问DB,对DB造成大量的访问。甚至会导致整个服务的瘫痪。这种现象就是Redis的雪崩。
    
    ## 如何防止雪崩?
    上面我们说到,雪崩产生的原因和过期时间有关,那么我们解决了过期时间集中就可以了.
    1、给缓存的过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
    2、对于Redis瘫痪可以利用集群+哨兵
    
    # 什么是穿透?
    再来聊一种场景,例如现在缓存了100个用户的信息,他们的id是1~100,那么当黑客请求id为-1的接口,就会导致直接去请求数据库,并且再访问数据库之后不会将数据缓存到redis中。如果穿透发生了同样会使得整个服务瘫痪。
    
    ## 如何防止穿透?
    解决缓存穿透也有两种方案
    1、对于不合法的请求,可以使用过滤器提前拦截。不合法就不让这个请求到达DAO层。
    2、当数据不存在时,在缓存中缓存一个空对象。下次请求时,就可以从缓存中获取啦,不过使用这种方法,一般都会设置一个比较短的过期时间。
    

    如何保证Redis中数据和MySQL(OtherDB)的一致性

    # 更新操作
    一般来说,对于更新操作,我们会有两种选择:
    1、先操作数据库,再操作缓存
    2、先操作缓存,在操作数据库
    
    首先我们要明确的时,无论我们先选择哪个,我们都希望这两个要么同时成功, 要么同时失败,所以这就演变为了一个分布式事务的问题。
    
    如果原子性被破坏了,可能会有以下的情况:
    数据库成功了,缓存操作失败了
    缓存操作成功了,数据库操作失败了
    
    ## 操作缓存
    更新时,更新缓存也有两种方案
    1、更新缓存
    2、删除缓存
    我们一般都是采用删除缓存的策略,原因是更新更容易导致缓存与数据库不一致的问题。
    
    先删除缓存,咋更新数据库在高并发的情况下表现不是很好,先更新数据库,再删除缓存在高并发情况下表现更好,但是原子性容易被破坏。
    
    
    

    集群 哨兵

    所谓集群,就是通过增加服务器的数量,使得服务器达到一个稳定的、高可用的状态。

    单机的redis虽然提供了RDB+AOF的策略。但是如果Redis宕机,也是灾难性的。为了提高redis的可用性,我们必须对他进行集群。

    # 集群
    部署多台Redis,有三种方案。twemproxy、codis、redis cluster3.0。这里不进行深入研究了。
    
    ## 主从复制
    redis的集群中,每一个redis都称之为节点
    节点有两种类型,主节点master和从节点slave
    redis集群是基于redis主从复制实现的
    只要网络连接正常,master都会将自己的数据同步到slaves中,保持主从同步
    
    ## 节点特点
    主节点可读、可写从节点只读
    
    
    ## 哨兵
    主从有一个弊端,就是当主节点挂了以后,整个集群就没有主节点了。所以在这种设计模式下,又出现了哨兵的机制,哨兵的作用就是对一个或者多个Redis集群进行监控和提醒,当哨兵监控到主节点出现故障之后,就会通知其他节点开会,由这些节点投票选取票数最高者作为主节点。当选的从节点自动成为主节点。原master修复重新上线后会自动转换为从节点。
    

    分布式锁

    Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁。
    将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作
    
    解锁:使用 del key 命令就能释放锁
    解决死锁:
    1)通过Redis中expire()给锁设定最大持有时间,如果超过,则Redis来帮我们释放锁。
    2) 使用 setnx key “当前系统时间+锁持有的时间”和getset key “当前系统时间+锁持有的时间”组合的命令就可以实现。
    

    SpringBoot中使用Redis

    1、引入启动器
    2、配置类中初始化redisTemplate属性
    3、创建Redis工具类,封装常用操作。由于工具类还是需要使用2,所以其也需要被Spring扫描。
    4、注入工具类,使用~
    
  • 相关阅读:
    在CentOS-6.3环境下,利用grub工具手工制作Linux U盘安装盘
    Windowns DOS For 循环实例
    Bootstrap 标签的变体 实例样式
    Bootstrap两端对齐的导航实例
    bootstrap 分页样式代码
    C# 微信扫码支付API (微信扫码支付模式二)
    AjaxFileUpload 在C#中应用
    关于百度编辑器UEditor(1.4.3)在C#.NET中的应用实例
    电脑运行状态
    网络测试
  • 原文地址:https://www.cnblogs.com/zhangruifeng/p/13573594.html
Copyright © 2020-2023  润新知