Redis相关知识

1.Redis事务
在这里插入图片描述
Redis事务以MULTI开始,中间添加多种命令,这些命令不会立即执行,而是被放入到一个队列中,当执行EXEC时,队列中的所有命令被依次执行。
  当命令放在MULTI中,但还未执行EXEC时,每个命令返回值为QUEUED,Redis事务将多个命令使用MULTI包括起来,调用EXEC一起执行,减少与客户端之间通信往返次数,提升执行多个命令时的性能
  
  在这里插入图片描述
  在这里插入图片描述
  从2.6.5版本开始,在执行EXEC之前,redis命令在加入队列时,如果出现错误(一般为语法错误),则执行EXEC时,该事务不会被执行,并自动丢弃
  事务监听
watch key1 key2 …  #监听一个或多个key unwatch #取消所有的监听

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。

WATCH命令是一种乐观锁的实现,基于CAS,watch必须与multi一起使用,才会发生作用,并且其必须在multi之前执行
2.Redis持久化
将数据(如内存中的对象)保存到可永久保存的存储设备中。
2.1 RDB
是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据。1、 RDB核心规则配置(redis.conf 文件,SNAPSHOTTING 对应内容)
在这里插入图片描述

save <指定时间间隔> <执行指定次数更新操作>
官方出厂配置默认是 900秒内有1个更改,300秒内有10个更改以及60秒内有10000个更改,则将内存中的数据快照写入磁盘

触发RDB快照
1 在指定的时间间隔内,执行指定次数的写操作,
2 执行save(阻塞, 只管保存快照,其他的等待) 或者是bgsave (异步)命令 ,
3 执行flushall 命令,清空数据库所有数据,意义不大,
4 执行shutdown 命令,保证服务器正常关闭且不丢失任何数据。
RDB 的优缺点:
优点:1 适合大规模的数据恢复,在恢复大数据集时的速度比 AOF 的恢复速度要快2 如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
缺点:1 数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。2 备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍),最后再将临时文件替换之前的备份文件。所以Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。

2.2 AOF
Redis 默认不开启,需要手动开启AOF持久化方式(appendonly no)。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
配置文件
指定更新日志条件
在这里插入图片描述

appendfsync always:同步持久化,每次发生数据变化会立刻写入到磁盘中。性能较差当数据完整性比较好(慢,安全)
appendfsync everysec:出厂默认推荐,每秒异步记录一次(默认值)
appendfsync no:不同步

配置重写触发机制
在这里插入图片描述
当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。一般都设置为3G,64M太小了
触发AOF快照
每次执行每次触发,可以是每秒触发,可以不同步
AOF 的优缺点
优点:数据的完整性和一致性更高缺点:因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。
redis还可以同时使用AOF持久化和RDB持久化,在这种情况下,当redis重启时,它会有限使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比RDB文件所保存的数据集更加完

持久化只需开启,无需关心加载,Redis每次启动的时候,检测持久化文件,自动加载

RDB和AOF区别?
1、触发条件不一样
rdb:时间和次数 aof:时间(每秒 、时刻)
2、存储的内容不一样
rdb:存储所有的命令
aof:写的命令保存到文件中
3、性能差异
rdb:低数据量下,性能高
aof:数据量大,性能高
3.过期策略
3.1定时删除
含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在 key的过期时间来临时,对key进行删除
优点:保证内存被尽快释放
缺点:
若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key
定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重(没人用)
3.2惰性删除
含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
3.3定期删除
含义:每隔一段时间执行一次删除过期key操作
优点:
通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用–处理"定时删除"的缺点
定期删除过期key–处理"惰性删除"的缺点
缺点
在内存友好方面,不如"定时删除"
在CPU时间友好方面,不如"惰性删除“

Redis中同时使用了惰性过期和定期过期两种过期策略

4.内存淘汰策略
Redis 用作缓存时, 如果内存空间用满,达到maxmemory极限,就会自动驱逐老的数据。需要使用LRU淘汰算法来决定清理掉哪些数据,以保证新数据的存入。
可以通过配置redis.conf中的maxmemory这个值来开启内存淘汰功能
maxmemory 配置指令 :maxmemory 100mb
将 maxmemory 设置为 0, 则表示不进行内存限制, 对32位系统来说有一个隐性的限制条件: 最多 3GB 内存。当内存使用达到最大限制时,如果需要存储新数据,根据配置的淘汰策略不同,Redis可能直接返回错误信息,或者删除部分老的数据
1、noeviction:当内存使用达到阈值时,所有引起申请内存的命令会报错,默认策 略
2、 allkeys-lru :在主键空间中,优先移除最近未使用的key
3、 volatile-lru :在设置了过期时间的键空间中,优先移除最近未使用的key
4、allkeys-random:在主键空间中,随机移除某个key
5、volatile-random:在设置了过期时间的键空间中,随机移除某个key
6、volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除
根据自身系统特征:

在Redis中,数据有一部分访问频率较高,其余部分访问频率较低,或者无法预测数据的使用频率时,设置allkeys-lru是比较合适的。

如果所有数据访问概率大致相等时,可以选择allkeys-random。

如果研发者需要通过设置不同的ttl来判断数据过期的先后顺序,此时可以选择volatile-ttl策略。

如果希望一些数据能长期被保存,而一些数据可以被淘汰掉时,选择volatile-lru或volatile-random都是比较不错的。

由于设置expire会消耗额外的内存,如果计划避免Redis内存在此项上的浪费,可以选用allkeys-lru 策略,这样就可以不再设置过期时间,高效利用内存了。
LRU
redis采用的LRU是非精准的LRU算法,基于抽样实现;由于redis是单线程的,如果采用全量的数据进行LRU计算,会比较消耗CPU资源;redis提供了一个重要参数:
#maxmemory-samples 5
该参数表示,每次随机选出5个不经常使用的key进行移除;配置的 参数值越大,其LRU结果能接近全量LRU的结果;但同时会给CPU带来比较大的开销,因此如果仅仅将redis作为LRU缓存服务使用,建议保持默认配置即可。
驱逐过程:

1、客户端执行一个命令, 导致 Redis 中的数据增加,占用更多内存。

2、Redis 检查内存使用量, 如果超出 maxmemory 限制, 根据策略清除部分 key。

3、继续执行下一条命令, 以此类推。

在这个过程中, 内存使用量会不断地达到 limit 值, 然后超过, 然后删除部分 key, 使用量又下降到 limit 值之下。

Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。

Redis缓存功能,是由edis.c文件中的freeMemoryIfNeeded函数实现的。如果maxmemory被设置,那么每次在执行命令钱,该函数都会被调用来判断内存是否够用、释放内存、返回错误。如果没有足够的内存程序主逻辑将会阻止设置了REDIS_COM_DENYOOM flag的命令执行,对其返回command not allowed when used memory > ‘maxmemory’的错误消息。

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

5.Redis缓存典型的问题

1、缓存穿透
  当查询一条数据,该数据不存在缓存和数据库的时候,每次请求都会请求到数据库。这种现象就叫缓存穿透。

当一个人拿一个并不存在的 id 一直查询,就会产生大量的请求到数据库查询,数据库就可以因为压力过大而崩掉。

解决办法:

1)、对空值做缓存;

2)、用一个布隆过滤器,将所有可能存在的数据库哈希到一个足够大的bitmap,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。 3)设置key规则

优缺点:第一种解决方法,如果是攻击的时候用大量不存在的 id 去请求,可能在缓存中产生大量的 key 和 值 null,可能会不太适合。第二种方案可以直接过滤掉不存在的 id,这样对缓存的压力不大。
2、缓存击穿
  在高并发系统中,大量的请求同时查询一个 key 时,而这个 key 正好失效,就会导致大量的请求都到数据库。
  可能会造成数据库请求量过大,压力增大。

解决办法:高并发是多线程同时去请求,可以在第一个查询数据的请求上使用一个互斥锁,其他线程到达缓存就等待。等第一个线程查询到数据,缓存到缓存工具里,然后第二个线程就可以拿到数据了。

3、缓存雪崩
  某一时刻发生大规模的缓存失效的情况,比如缓存服务器停电,宕机等。此时请求就会大量到数据库。这种现象就叫缓存雪崩。

解决办法:使用集群缓存,分布式架构。并且使用 Hystrix 限流&降级,当发生很多失败的请求时,就对请求限流或者降级。开启缓存持久化机制,尽快恢复缓存集群。设置一个失效时间随机数
  
Redis是单进程单线程的,并发问题如何解决

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。有2种解决方法:
   1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
   2.服务器角度,利用setnx实现锁。   注:对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值