1 NoSQL数据库简介

1.1 技术发展

解决分布式服务器架构中存在的session问题,

  1. 存储在内存中,缓解CPI、IO压力
  2. 不需要复制,缓解内存压力

    1.2 NoSQL数据库

    Not Only SQL,非关系型数据库

  3. 不遵循SQL标准

  4. 不支持ACID
  5. 远超SQL的性能

以数据本身特点存储,强调性能。

2 Redis概述和安装

EUT)352A18UOIM09UJIE50N.png

2.1 应用场景

  1. 配合关系型数据库做高速缓存
    1. 高频次热门数据
    2. 分布式架构,session共享
  2. 多样数据结构存储持久化数据

    2.2 Redis安装

    3 常用5大数据结构

    3.1 String

    3.2 List

    ziplist是列表元素较少的情况下使用一块连续的内存存储,所有元素紧挨存储。避免过多双向指针消耗存储空间。
    quickList元素较多时,将多个ziplist双向指针串起来。

    3.3 Set

  • 定义:string类型的无序集合,底层是所有值null的哈希表。

    3.4 Hash

    )GBA0PJ8%F_3W~4I1`4LVCJ.png![W~ML]04Z1P9FI~USEU@B)6.png

    3.5 Zset

    有序的没有重复元素的字符串集合。
    每个成员有一个评分(score)。
    它等价于Map数据结构。

    3.5.1 跳跃表

    4 配置文件

    5. 订阅和发布

    6 Redis6新数据类型

    6.1 Bitmaps

    %5C{9VVB%~HWNGN)QI_4H(W.png
    对于稠密的图,使用bitmap比set节约空间。

    6.2 HyperLogLog

    基数问题:计算不重复个数
    在固定空间里,尽可能多的维护不重复的值,不存储真实值。

    6.3 Geospatial

    地理

    7 Jedis操作Redis6

    8 Redis6和spring boot整合

    9 Redis6的事务操作

    9.1 事务定义

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

    9.2 事务使用

  1. 组队阶段(语法错误,在exec时所有队列中命令会错误)
  2. 执行阶段(执行错误,在exec时,执行错误命令失败,其他正常命令不受影响)

    9.3 事务冲突

    解决事务冲突,加锁。

    9.3.1 悲观锁

    每次操作之前,都上锁。等你操作完后再操作。

    9.3.2 乐观锁

    对数据加上版本号,修改值后更改版本号。每次修改前查看数据版本号与数据库中数据版本号是否一致。
    watch:模拟乐观锁,当事务执行前数据被改变了,那么事务则不会得到执行。
    ![9T6ZMVIRWM)$KAUU0WX38M.png

    10 持久化

    定义:在指定时间间隔内将内存中的数据集快照写入磁盘。

    10.1 RDB

    默认开启
    通过fork一个子进程来实现备份操作,使用写时拷贝技术。
    最后一次持久化可能会丢失最后一次需要持久化数据内容。
    QB%H(NO_R(`9W0_BDVJ$XWM.png

    10.2 AOF (Append Only File)

    根据Redis执行过的所有指令记录下,只许追加文件但不可以改写文件。redis重启就是根据日志文件的内容将指令从前到后执行一次以完成数据的恢复工作。
    默认不开启。系统优先读取AOF数据。
    备份和恢复数据和RDB基本一致。
    同步频率:always每次写立刻记录everysec每秒记录no不主动记录
    重写压缩操作:只关注最终数据结果,不关注过程,所以重写冗余的命令。超过基本大小2倍,自动触发重写,fork进程实现。
    0I]TU2ZBDF@MB~$JTKJ1$5J.png

    11 主从复制

    11.1 简介

    一般都一主多从,主从复制原理如下。
    )$EBVDRHQZK@B%)9{GM33{5.png

    11.2 一主两从

    从服务器挂掉之后,再重启不会自动变为从服务器。
    主服务器挂掉之后,从服务器不会上位,会等待主服务重启。

    11.3 薪火相传

    可以多级。

    11.4 反客为主

    将从机变为主机,手动slave no one

    11.5 哨兵模式

    反客为主自动版。]B%QPPIF9XZCIRI(`]L~QB6.png

    12 集群

    集群的作用:

  3. 容量不够,扩容。

  4. 并发写操作,分摊写。

无中心化集群。
特点:集群中每个主机都能作为入口,平均分配了写入压力。
插入值时,使用CRC16(key)%16384计算键key属于哪个槽,CRC16语句用于计算键key和CRC16校验和。
集群中每个主节点分别处理一部分插槽。
插入多个值,可以使用组插入。
集群恢复类比哨兵。

13 一些问题

13.1 缓存穿透

原因:

  1. redis查询不到数据库(需要频繁查询数据库造成数据库崩溃)
  2. 出现很多非正常url访问(恶意攻击)

解决方案:

  1. 空值缓存:查询结果为null,也对空结果进行缓存,但是设置这个空结果的过期时间很短,最长不超过5分钟。
  2. 设置可访问的白名单:使用bitmaps类型定义一个可访问的名单,不在bitmaps里面的用户不允许访问。
  3. 采用布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmaps里面,一个一定不存在的数据就会被这个bitmaps拦截,从而降低对底层存储系统查询压力。
  4. 实时监控:发现Redis命中率急速降低,需要人为排查访问对象和访问数据。

    13.2 缓存击穿

    现象

  5. 数据库访问压力瞬时增加

  6. redis里面没有出现大量key过期
  7. redis正常运行

原因

  1. redis某个key过期,但却被大量访问使用这个key

解决方案

  1. 预先设置热门数据,加长这些热门数据key的时长
  2. 实时调整:实时调整key的过期时长
  3. 锁:缓存未命中时,先加锁再去加载数据。

    13.3 缓存雪崩

    现象

  4. 服务器压力过大崩溃

原因

  1. 极少时间段,查询大量key集中过期

解决方案

  1. 构建多机缓存架构:nginx缓存+redis缓存+其他缓存(ehcache等)
  2. 使用锁或者队列
  3. 设置过期标志更新缓存:记录缓存数据是否过期,如果过期触发通知另外线程在后台去更新实际key的缓存
  4. 将缓存失效时间分散开:在原有失效时间上加上一个随机值,避免集体失效事件。

    13.4 基于redis分布式锁