记录一下对redis的理解~

Redis

基础信息

Redis是一个开源的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。实现语言是c语言。单线程。

Redis可以保存多种数据结构,它的存储基于内存,可以key-Value的形式保存;其保存格式类似于Map

为什么不用Map而使用Redis呢?
  1. Map是本地存储,无法保证多台机器的缓存一致性,而redis是分布式缓存,多台服务器共享
  2. Map存储的东西过多,Jvm容易挂掉,所以一般只用于做临时存储,它的有效性会随着jvm的销毁而结束,并且也必须需要手动去编写过期时间
  3. Redis可以将缓存数据写在硬盘里,不需要被程序的启动和关闭而影响,并且它提供了多样的数据结构和过期机制
为什么要使用缓存机制?

假设请求量和并发量特别大的时候,所有的信息都需要去数据库查询,这样就很容易让数据库挂掉,从而有性能问题(访问反应慢,无法获取数据等),因为数据库的读写都是要经过磁盘,然而磁盘的访问速度没有内存快;

redis 英文 redis 语言_服务器

Redis的数据结构

Redis是以key-value的形式存储,Key一定是字符串,则Vlaue可以是String,list,hash,set,sortset等数据结构

Redis并没有直接使用这些数据结构实现key-value的数据库,而是基于这些数据结构创建了一个对象系统,也就是说,Redis使用对象来表示key和value,新建一个键值对的时候则生成两个对象,key对象和value对象
对象都有type(类型)、encoding(编码)、ptr(指向底层数据结构的指针)来表示

Redis的基础信息

Redis的默认端口是6379,默认数据库数量为16,且不同数据库之间是具有隔离性的

过期时间

Redis是基于内存, 内存是有限的,所以我们会去掉一些不常用的数据,所以需要我们设置一下键的过期时间

  1. 设置键的生存时间可以通过EXPIRE或者PEXPIRE命令。
  2. 设置键的过期时间可以通过EXPIREAT或者PEXPIREAT命令
  3. PERSIST(移除过期时间)
  4. TTL(Time To Live)返回剩余生存时间,以秒为单位
  5. PTTL以毫秒为单位返回键的剩余生存时间
  6. 过期时间是保存在RedisDB中的一个叫做 expires的hash表中
过期策略

由于过期时间是保存在表中的,那么到了过期时间是否会直接执行删除呢?它会遵守什么样的过期策略呢?
过期策略分为如下三种1.定时删除(类似定时器的定时)2.惰性删除(取键的时候判断时候过期)3.定期删除(类似定时器的每隔多久)
Redis采用的是惰性删除和定期删除。所以不一定会及时删除的

持久化

因为redis基于内存,如果服务器重启/断电导致了redis的重启,内存数据将会丢失
所以redis有两种持久化的策略:

  1. RDB:
    它所生成的 RDB 文件是一个压缩的二进制文件,基于快照的方式,通过该文件可以还原生成 RDB 文件时的数据库状态
    创建方法:
    有两个命令可以生成 RDB 文件,一个是 SAVE(阻塞Redis服务器进程)、另一个是 BGSAVE(fork一个子进程,父进程继续处理,写完数据库后新的RDB文件会替换旧)
    文件载入:
    没有开启AOF持久化,RDB 文件的载入是在服务器启动时自动执行的,所以没有用于载入的命令,期间阻塞主进程。
  2. AOF:Append-only-file的简写,当redis执行命令时候,将命令写入AOF文件中
    实现步骤:
    命令追加、文件写入、文件同步

过期键的处理方式

  1. RDB:创建的时候,过期键不会保存;载入的时候,过期键不会载入
  2. AOF:如果键过期,但是并未被删除,AOF会保留但是没有实际影响,因为如果过期键被删除,会追加一条DEL命令去记录,在重写AOF文件的时候,程序会对键进行检查,如果过期则会被删除

Redis是单线程的

Redis服务器主要处理文件事件(基于socket通信,I/O多路复用)和时间事件(基于serverCron)
Redis单线程快:1.纯内存操作2.核心是非阻塞I/O 3.单线程就避免了多线程的上下文切换的问题

Redis主从复制(master/replica)

如果访问请求过多,为了提高服务的高可用性,我们可以增加Redis服务器进行主从管理
主服务器负责写请求,从服务器负责读请求
好处:

  • 读写分离
  • 高可用 :如果某台服务器挂了,其他服务器还能接受请求
  • 处理高并发量
复制功能

在Redis中,用户可以通过执行SALVEOF命令或者设置salveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(salve)
具体体现形式:

  • 同步(sync):将从服务器的数据库状态更新至主服务器的数据库状态
  • 命令传播(command propagate):主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致,让主从服务器的数据库状态重新回到一致状态。
复制步骤
  • 从服务器设置主服务器的IP和端口
  • 建立与主服务器的Socket连接
  • 发送PING命令(检测Socket读写是否正常与主服务器的通信状况)
  • 身份验证(看有没有设置对应的验证配置)
  • 从服务器给主服务器发送端口的信息,主服务器记录监听的端口

Redis机制

如果主服务器挂了,Redis提供了哨兵机制去将一台从服务器提升成主服务器,等到主服务器恢复好则变成从服务器

哨兵(Sentinel)模式的原理及功能
  • 不停地监控主从服务器是否正常工作(两秒也刺激)
  • 如果有故障,哨兵发送信息通知管理员
  • 如果主服务器挂了,会主动提升从服务器成主服务器,且配置文件修改
  • 哨兵可以作为配置中心,提供当前主服务器的信息

Redis故障

缓存雪崩
可能情况

Redis挂掉了,请求直接访问数据库或者是键都设置同一过期时间,同时失效

解决方案
  • 在缓存设置过期时间的时候加上随机值,这样会避免同时过期造成的雪崩
  • 可以设置主从复制+哨兵,有效避免redis服务器挂掉造成的影响,提高可用性
缓存穿透

无限制的去请求一个不可能存在的数据(比如说id为负数),由于缓存无法集中,所以造成大量的访问数据库。

解决方案
  • java中的过滤器(filter)拦截
  • 将请求数据库找不到的数据以空的形式放入缓存,设置较短的过期时间

Redis数据和数据库数据一致性

执行更新操作有两种选择(必须遵守原子性:一起成功一起失败):

  • 先操作数据库,在更新缓存(默认删除缓存在插入)
  • 先更新(同上)缓存在更新数据库
解决方案
更新数据库–>删除缓存

高并发的情况几率小:由于读操作会比写操作简单,并且写操作会在写的时候锁表,所以读操作必须要在写操作之前进入,又要晚于写操作更新缓存

删除缓存–>更新数据库

1.放入队列,实行串行化