目录
- 概述
- 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重新放入到缓存中