Redis详解

Redis?

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis的五个基本类型

#SET               设置key
#GET               查看key的值
#EXPIRE         设置key的过期时间
#TTL                查看key剩余的时间
#EXISTS         判断当前的key是否存在
#KEYS   *        查看当前所有的key
#DEL   key       删除当前的key
#TYPE             查看key存储的value的类型

1、字符串strings:在遇到数值操作时,redis会将字符串类型转换成数值。
(1)set get
设置值和获取值:格式: set key value get key
(2)exists
判断key是否存在,格式:exists key
(3)append
追加字符串,如果key不存在,相当于set命令,格式:append key value
String类似的使用场景:value除了是字符串也是数字

  • 计数器
  • 统计多单位的数量
  • 对象缓存存储

2、列表list:在Redis中,我们可以把list完成栈、队列、阻塞队列,所有的list命令都是l开头的。
(1)lpush rpush lrange
从list左边或者右边插入值:lpush key value rpush key value
获取指定范围的值:lrange key start stop
(2)lpop rpop
从列表的左边或者右边移除值,格式:lpop key rpop key
(3)lindex
获取指定下标的值:lindex key index
3、集合set:set中的只是不能重复的
(1)sadd
给set中添加值:sadd key value1 value2 ...
(2)smembers
获取set中的所有值:smembers key
(3)srandmember
从set中获取随机值:srandmember key count
4、哈希hash:可以讲哈希堪称是一个map集合,key-value中的value是一个map集合
(1)hset hget
设置或者获取一个hash的值:hset key field1 value1 hget key field
(2)hmset hmget
设置或者获取hash的值:hmset key field value1 field2 value2 ... hmget key field1 field2
(3)hdel
删除指定field的hash键值对:hdel key field
hash更适合对象的存储,String更加适合字符串存储
5、有序集合zset
(1)zadd
添加一个值:zadd key scores value
(2)zrange
获取zset中一个范围的值:zrange key start stop

Redis的持久化

RDB持久化

RDB是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法;Redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行I/O操作的,对数据恢复的完整性不是非常敏感的,RDB方式要比AOF更加高效。RDB的缺点是最后一次持久化后的数据可能丢失。
rdb保存的文件是dump.rdb

触发机制

  1. save的规则满足的情况下,会自动触发rdb操作
  2. 执行flushall命令,会触发rdb操作
  3. 对出redis时,也会触发rdb操作

如何恢复RDB文件

只需要将rdb文件放在redis的启动目录下就可以。redis启动时会自动检查dump.rdb文件恢复其中的数据。
RDB优点:
适合大规模的数据恢复。
对数据的完整性要求不高。
RDB缺点:
需要一定的时间间隔进行操作,如果redis意外宕机,最后一次持久化后的操作数据就没有了。
fork进程的时候,会需要占用一定的内存空间。

AOF持久化

只允许追加不允许改写的文件。
追加日志时,恰好遇到磁盘空间满,inode满或断电等情况导致日志写入不完整,redis-check-aof工具可以用来进行日志修复。
采用追加方式,如果不做任何处理,AOF文件会变得越来越大,redis提供了AOF文件重写机制,即当AOF文件的大小超过所设定的阀值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。

AOF出现被写坏的情况

修复出错文件的步骤:
1、备份被写坏的AOF文件
2、运行redis-check-aof-fix进行修复
3、用diff-u来看下两个文件的差异,确定问题点
4、重启redis,加载修复后的AOF文件

AOF重写

在重写即将开始之际,redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。

Redis的事务处理

redis事务处理的基本指令

MULTI用来组装一个事务;
EXEC用来执行一个事务;
DISSCARD用来取消一个事务;
WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。

redis> MULTI //事务开始
OK
redis> INCR user_id //多条命令按顺序入队
QUEUED
redis> INCR user_id
QUEUED
redis> INCR user_id
QUEUED
redis> PING
QUEUED
redis> EXEC //执行

  1. (integer) 1
  2. (integer) 2
  3. (integer) 3
  4. PONG

Redis发布-订阅

Redis发布订阅(pub/sub)是一种消息通信模式:发布者发送消息,订阅者接收消息。

相关命令:

//订阅一个或多个符合给定模式的频道
PSUBSCRIBE pattern [pattern ...]

//查看订阅与发布系统状态
PUBSUB subcommand [argument [argument...]]

//退订所有给定模式的频道
PUNSUBSCRIBE [pattern [pattern ...]]

原理:
Redis是使用C实现的,通过分析Redis源码里的pubsub.c文件,了解发布和订阅机制的底层实现,借此加深对Redis的理解。
Redis通过PUBLISH、SUBSCRIBE和PSUBSCRIBE等命令实现发布和订阅功能。
通过SUBSCRIBE命令订阅某频道后,redis-server里维护一个字典,字典的键就是一个个channel,而字典的值则是一个链表,链表中保存了所有订阅这个channel的客户端。SUBSCRIBE命令的关键,就是将客户端添加到给定channel的订阅链表中。
通过PUBLISH命令向订阅者发送消息,redis-server会使用给定的频道作为键,在它所维护的channel字典中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。
Pub/Sub从字面上理解就是发布(Publist)与订阅(Subscribe),在Redis中,可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅他的客户端都会受到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能。

使用场景:

  1. 实时消息系统
  2. 实时聊天 – 频道当做聊天室,将信息回显给所有人即可
  3. 订阅,关注系统都是可以的
  4. 用消息队列中间件

Redis主从复制

基础

主从复制:指的是将一个Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower)。 数据的复制是单向的 ,只能从主节点到从节点。Master以写为主,Slave以读为主。
默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或者没有从节点),但一个从节点只能有一个主节点。

作用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务冗余。
  3. 负载均衡:在 主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过从节点分担读负载,可以大大提供Redis服务器的并发量。
  4. 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实现的基础,因此说主从复制是Redis高可用的基础。

复制原理

全量复制 :Slave服务在接受到数据库文件数据后,将其存盘并加载到内存中。
增量复制 :Master继续将新的所有收集到的修改命令一次传给Slave,完成同步。

哨兵模式

主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis从2.8开始正式提供了Sentinel(哨兵)架构来解决这个问题。

某草篡位的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将 从库转换为主库。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个单独的进程,作为进程,他会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

哨兵的作用:

  1. 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  2. 当哨兵监测到Master宕机,会自动将Slave切换成Master,然后通过发布/订阅模式通知其他的从服务器,修改配置文件,让它切换主机。

哨兵模式的优点:

哨兵集群,基于主从复制模式,所有的主从复制优点,它全有。
主从可以切换,故障可以转移,系统的可用性会更好。
哨兵模式就是主从模式的升级,手动转自动,更加健壮。

哨兵模式的缺点:

Redis不好在线扩展,集群容量一旦到达上限,在线扩容十分麻烦。
实现哨兵模式的配置很麻烦,里面有很多选择。

Redis缓存穿透和雪崩

Redis缓存的使用,极大的提高了应用程序的性能和效率,特别是数据查询等。但同时,它也带来了一些问题。其中,最主要的问题就是数据一致性,从严格意义上来讲,这个问题是无解的。如果对数据一致性要求很高,那么就不能使用缓存。

缓存穿透

缓存穿透的就是用户想要查询一个数据,发现Redis中没有,也就是缓存没有命中,于是向持久层数据库发起查询,发现也没有这个数据,于是本次查询失败。当用户很多的情况下,缓存都没有命中,又都去请求持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于缓存穿透。

解决方案1 -- 布隆过滤器

布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合的则丢弃,从而避免对持久层数据库的查询压力。

解决方案2 -- 缓存空对象

当存储层不命中后,及时返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个
数据将会从缓存中获取,保护了后端数据源。

缓存击穿

缓存击穿,是指一个key非常热点。在不停的扛着大量并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在也给屏蔽上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且写会缓存,会导致数据库瞬间压力过大。

解决方法1 -- 热点数据永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。

解决方案2 -- 加互斥锁

分布式锁: 使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验比较大。

缓存雪崩

缓存雪崩指的是在某一时间段,缓存集中过期失效,或者Redis宕机。比如:在写文本的时候,马上要到双十一零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就过期了。从而对这批商品的访问查询,都落到了后台数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会宕机的情况。

解决方法1 -- Redis高可用

这个思想就是说既然Redis有可能挂掉,我就多增设几台Redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建缓存服务器集群。(异地多活)

解决方案2 -- 限流降级

这个思想就是在缓存失效后,通过加锁或者队列来控制读写数据库的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

解决方案3 -- 数据预热

数据预热的含义就是在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

参考文献

https://blog.csdn.net/liqingtx/article/details/60330555

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值