目录

  • 概述
  • NoSql
  • Redis
  • Redis数据类型
  • String
  • List
  • Set无序,不重复
  • Zset:有序集合
  • Hash
  • Redis线程模型
  • Redis是单线程的还是多线程的?
  • 为什么单线程操作速度还是很快?
  • Redis持久化
  • RDB方式
  • AOF方式
  • Redis事务
  • 主从复制
  • 哨兵机制
  • key的过期策略
  • 缓存穿透 缓存击穿 缓存雪崩


概述

NoSql

泛指非关系型数据库,不仅仅是sql,mysql是关系型数据库,在信息量巨增的环境下,出现了非关系型数据库;

关系型数据库:以数据库表为单位存储,表与表之间存在关联关系

非关系型数据库:数据与数据之间没有关系,数据就是以键值对的方式存储,通过键获取到值即可,例如:Redis数据库

Redis

特点:可以将数据存储在内存中,导致读写的速度非常快

数据结构比较简单,以键值对进行存储

支持高性能,缓存数据,使其更加灵活方便

支持数据持久化(临时在硬盘上的备份,键值对)

Redis数据类型

数据在存储中,键都是String类型,只有值可能会有多种数据类型,但是目前一般使用String类型

String

Redis中最基本的数据类型,一个key对应一个value

使用场景

缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力

计数器:redis是单线程模型,记录浏览器点赞量,访问量

session:常见方案spring session + redis实现session共享

List

• lpush key value[value…] 将一个或多个值插入到key列表的表头(最左边)

• rpush key value[value…] 将一个或多个值插入到key列表的表尾(最右边)

• lpop key 移除并返回key列表的头元素

• rpop key 移除并返回key列表的尾元素

•lrange key start stop 返回列表key中指定区间内的元素,区间以偏移量start和stop

实现栈和列表的操作

Set无序,不重复

• sadd key member[member…] 往集合key中存入元素,元素存在则忽略,若key不存在则新建

• srem key member[member…] 从集合key中删除元素

• smembers key 获取集合key中所有元素

• scard key 获取集合key的元素个数

Zset:有序集合

Hash

• 适合存储对象(适合对对象中的每个属性进行值的修改的)

• hset key field value 存储一个哈希表key的键值

• hmset key field value [field value …] 存储多个键值对

• hget key field 获取哈希表key对应的field键值

• hmget key field [field …] 批量获取哈希表key中多个field键值

• hdel key field [field …] 删除哈希表key中的field键值

Redis线程模型

Redis是单线程的还是多线程的?

在Redis6.x之前它是彻彻底底的单线程的,不论是监听客户端连接还是数据的读写操作,都是线程的,它们的操作都是单线程的

在Redis6.x之后,它就是在数据监听以及其他操作时添加额外的线程,但是在数据读写操作时,还是单线程的,因为但线程不会出现并发安全问题,而且还能够保证原子性

为什么单线程操作速度还是很快?

• 它是基于内存操作的,底层是一个哈希表结构,时间复杂度为o(1)

• Redis的瓶颈并不是CPU决定的,而是网络的带宽以及内存决定的

• Redis是属于多路复用以及非阻塞IO

• 单线程避免了上下文切换,性能提高

底层实现

它的全局是一个哈希表结构,可以直接通过key来计算出哈希值,找到对应的entry位置,entry中保存的 不仅有key—value,还有其他的内容,因此在查找过程中性能就比较高

Redis持久化

假如在Redis中存储数据时,如果出现了断电或者宕机的情况,数据可能会丢失,但是Redis在这种情况下,有一定的处理办法来保证数据的持久化

RDB方式

它是定期地将数据快照(内存中有许多的k-v数据,它是将其数据直接拍照)保存在一个dump.rdb文件中,RDB方式是Redis默认支持的,不需要手动配置

里面有触发RDB快照的条件:

save 900 1:900秒内至少有一个键被更改则进行快照

save 300 10;

save 60 1000;

在Redis客户端模式中使用shutdown save 命令关闭Redis时,保存快照,在重启时还原

AOF方式

AOF则是使用日志的方式进行记录Redis的所有操作命令,不是默认支持的,这必须手动开启(appendonly no —yes )

可以进行设置什么时候进行记录 appendfsync always ; appendfsync everysec

Redis事务

Redis事务它是可以将多条命令放入到一个队列中执行,不受其他客户端的影响,在同一个事务中执行,但是不会保证原子性(也就是中间执行错误时,也会添加到队列中的)

multi 开启事务

命令1

命令2

exec 提交事务

主从复制

在大型项目中,为了系统的稳定运行,配置一台服务器为主机,多台服务器为从机,主机负责写数据,并且将主机的数据同步到从机中,从机负责读数据,实现读写分离

即使在使用期间,有一个服务器出现故障,那么其他的服务器也可以正常工作,当有问题的服务器排除故障恢复后,还能够继续工作,即使是主机故障,也可以从多台服务器中选举出一台作为主机(哨兵机制)

作用:

集群机制,必将存在数据冗余以及服务冗余

实现负载均衡(当有多台机器作为服务器时,如果有多个请求同时访问,那么会有一种策略保证哪些请求进入哪些服务器)

实现读写分离,多台服务器负责读操作,实现高可用

哨兵机制

Redis主机可能会出现问题,那么就有一套哨兵机制进行监听监测,它是独立运行的一个进程,在一段时间内它会定期地向服务器发送消息,如果不回复,则说明出现了问题,则通过一套选举机制在多个从机中选举一个服务器作为主机,当主机故障恢复后,则临时主机又变为从机继续工作

key的过期策略

在使用Redis时,我们将key设置过期时间,但是key在时间达到之后,不会立即删除,它会 有一定的策略进行删除

立即删除

设置key时,会创建一个回调函数,在key时间到期时,会立即调用回调函数进行删除,但是如果同一时刻有多个key时间到期,如果同时删除的话,导致CPU损耗比较大,不太友好

惰性删除

key到期之后不会立即删除,而是会等到下次再使用时,会检测出key过期,才会进行删除,但是这一做法会占用内存空间,导致资源浪费

定时删除

它也不会立即删除,而是将过期的key记录下来,定期对这些过期key进行删除,这样既减轻了CPU的消耗,也减轻了内存空间的消耗

Redis将惰性删除以及定时删除结合使用

缓存穿透 缓存击穿 缓存雪崩

**缓存穿透:**在数据层进行访问时,首先会通过缓存进行访问数据,如果缓存中没有,则会在mysql数据库中进行访问,但是如果数据库中本身就没有此条数据,则缓存中肯定没有,因此每次都会访问到mysql数据库,因此还是没有能够起到缓解压力的作用,这就是缓存穿透

办法: 在访问之前进行参数的校验

将mysql数据库中的空数据也作为一个空对象缓存到Redis中,这样就会缓解压力

缓存击穿: 这是在mysql数据库中存在数据,但是在这一时间结点时,有多个请求进行访问,但是就是在这个时候Redis过期时间已经到了, 在缓存中找不到数据,则还是会去mysql数据库查询,因此就会造成数据库崩溃,这就是缓存击穿

办法: 将热点新闻设置为永不过期

加锁,首先让第一个请求进行访问,完了之后将数据缓存到Redis中,在之后请求中,缓存中有数据,则就会去Redis中查找,缓解压力

缓存雪崩: 大量的时间同时过期,因此就会造成mysql数据库会有大量的请求进行访问,这就是缓存雪崩

办法: 将过期时间随机设置,就不会出现过期时间同时到达

将热点新闻缓存到不同的从机中,以便于出现这种情况

不进行设置过期时间

设置定时任务,将快过期的key重新放入到缓存中