Redis 缓存 消息订阅 事务 雪崩 穿透

Redis

Redis五种数据类型和消息订阅 

String命令

String是最常用的一种数据类型,普通的key/value存储都可以归为此类

1:set/get 

设置key对应的值为String类型的value 

获取key对应的值 

2:mget
批量获取多个key的值,如果可以不存在则返回nil 

3:incr && incrby 

incr对key对应的值进行加加操作,并返回新的值;incrby加指定值 

4:incr && incrby 

incr对key对应的值进行加加操作,并返回新的值;incrby加指定值

5:setnx 

设置key对应的值为String类型的value,如果key已经存在则返回0

 6:setex 

设置key对应的值为String类型的value,并设定有效期 

其他命令 

getrange 获取key对应value的子字符串
mset 批量设置多个key的值,如果成功表示所有值都被设置,否则返回0表示没有任何值被设置  msetnx,同mset,不存在就设置,不会覆盖已有的key
getset 设置key的值,并返回key旧的值 append:给指定key的value追加字符串,并返回新字符串的长度 

Hash的命令

hash是一个String类型的field和value之间的映射表 (双层Hash)

 redis的Hash数据类型的key(hash表名称)对应的value实际的内部存储结构为一个HashMap 

Hash特别适合存储对象 

相对于把一个对象的每个属性存储为String类型,将整个对象存储在Hash类型中会占用更少内存。

 所存储的成员较少时数据存储为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht

 运用场景: 如用一个对象来存储用户信息,商品信息,订单信息等等。 

hset:设置key对应的HashMap中的field的value 

hget:获取key对应的HashMap中的field的value 

hgetall:获取key对应的HashMap中的所有field的value

hlen:返回key对应的HashMap中的field的数量 

List的命令 

lpush:在key对应的list的头部添加一个元素 

lrange:获取key对应的list的指定下标范围的元素,-1表示获取所有元素

 lpop:从key对应的list的尾部删除一个元素,并返回该元素 

rpush:在key对应的list的尾部添加一个元素 

rpop:从key对应的list的尾部删除一个元素,并返回该元素 

Set的命令 

 sadd:在key对应的set中添加一个元素

 smembers:获取key对应的set的所有元素

 spop:随机返回并删除key对应的set中的一个元素 

 suion:求给定key对应的set并集 

 sinter:求给定key对应的set交集 

SortSet的命令

set的基础增加顺序score,再根据score进行排序 

zadd:在key对应的zset中添加一个元素 

zrange:获取key对应的zset中指定范围的元素,-1表示获取所有元素 

zrem:删除key对应的zset中的一个元素 

zrangebyscore:返回有序集key中,指定分数范围的元素列表,排行榜中运用 

zrank:返回key对应的zset中指定member的排名。其中member按score值递增(从小到大); 排名以0为 底,也就是说,score值最小的成员排名为0,排行榜中运用 

set是通过hashmap存储,key对应set的元素,value是空对象 sortset是怎么存储并实现排序的呢,hashmap 存储,还加了一层跳跃表 跳跃表:相当于双向链表,在其基础上添加前往比当前元素大的跳转链接 

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间 件。 它支持多 种类型的数据结构,如 字符串(strings)、散列(hashes)、 列表(lists)、 集合 (sets)、 有序集合(sorted sets)等。 

Redis消息订阅发布 

作用:发布订阅类似于信息管道,用来进行系统之间消息解耦,类似于mq,rabbitmq、rocketmq、kafka、 activemq主要有消息发布者和消息订阅者。比如运用于:订单支付成功,会员系统加积分、钱包进行扣钱操 作、发货系统(下发商品) 

PUBLISH:将信息message发送到指定的频道channel。返回收到消息的客户端数量 

SUBSCRIBE: 订阅给指定频道的信息 

UNSUBSCRIBE: 取消订阅指定的频道,如果不指定,则取消订阅所有的频道。 

Redis的消息订阅发布和mq对比? 答:redis发布订阅功能比较薄弱但比较轻量级,mq消息持久化,数据可靠 性比较差,无后台功能可msgId、msgKey进行查询消息 

Redis事务机制 

MULTI 与 EXEC命令 

以 MULTI 开始一个事务,然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事 务中的所有命令 

DISCARD命令
DISCARD 命令用于取消一个事务, 它清空客户端的整个事务队列,然后将客户端从事务状态调整回 非事务状态, 最后返回字符串 OK 给客户端, 说明事务已被取消 

WATCH命令 

WATCH 命令用于在事务开始之前监视任意数量的键: 当调用 EXEC 命令执行事务时, 如果任意一个 

被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败 

redis事务与传统关系型事务的比较 

原子性(Atomicity) 

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。如果一个事务队列中的所有命令都被成功地执行,那么称这个事务执行成 功 

一致性(Consistency) 

       入队错误 

在命令入队的过程中,如果客户端向服务器发送了错误的命令,比如命令的参数数量不对,等 等, 那么服务器将向客户端返回一个出错信息, 并且将客户端的事务状态设为 REDIS_DIRTY_EXEC 。 

       执行错误 

如果命令在事务执行的过程中发生错误,比如说,对一个不同类型的 key 执行了错误的操作, 那么 Redis 只会将错误包含在事务的结果中, 这不会引起事务中断或整个失败,不会影响已执 行事务命令的结果,也不会影响后面要执行的事务命令, 所以它对事务的一致性也没有影响 

隔离性(Isolation) 

WATCH 命令用于在事务开始之前监视任意数量的键: 当调用 EXEC 命令执行事务时, 如果任 

意一个被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败

 持久性(Durability) 

因为事务不过是用队列包裹起了一组 Redis 命令,并没有提供任何额外的持久性功能,所以事 务的持久性由 Redis 所使用的持久化模式决定 

持久化

      RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

      AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

二者优缺点

RDB存在哪些优势呢?

1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数 据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。

2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。

3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。

4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

RDB又存在哪些劣势呢?

1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

AOF的优势有哪些呢?

1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其 效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变 化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。

2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操 作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据 一致性的问题。

3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创 建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

AOF的劣势有哪些呢?

1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。

redisTemplate api 

opsForValue 操作String,Key,Value,包含过期key,setBit位操作等 opsForSet 操作set
opsForHash 操作hash
opsForZset 操作SortSet 

opsForList 操作list队列
opsForHash 操作hash opsForZset 操作SortSet opsForList 操作list队列 

缓存雪崩 

     什么是缓存雪崩?你有什么解决方案来防止缓存雪崩?

                如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪 崩。 由于原有缓存失效,新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了,而对数据 库CPU 和内存造成巨大压力,严重的会造成数据库宕机 

     你有什么解决方案来防止缓存雪崩?

  1:加锁排队  

        key: whiltList value:1000w个uid 指定setNx whiltList value nullValue mutex互斥锁解 决,Redis的SETNX去set一个mutex key, 当操作返回成功时,再进行load db的操作并 回设缓存; 否则,就重试整个get缓存的方法 

  2:数据预热 

       缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在 用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的 缓存数据!可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触 发加载缓存不同的key

  3:双层缓存策略 

       C1为原始缓存, C2为拷贝缓存, C1失效时, 可以访问C2, C1缓存失效时间设为短期, C2设置为长期

  4: 定时更新缓存策略 

         失效性要求不高的缓存,容器启动初始化加载,采用定时任务更新或移除缓存

         设置不同的过期时间,让缓存失效的时间点尽量均匀

缓存穿透

       什么是缓存穿透?你有什么解决方案来防止缓存穿透?

                 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候, 在缓存中找不到对应key的value,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次 无用 的查询)。这样请求就绕过缓存直接查数据库 

        你有什么解决方案来防止缓存穿透? 

   1:采用布隆过滤器BloomFilter 

        将所有可能存在的数据哈 希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 

bitmap 拦截掉,从而避免了对底层存储系统的查询压力

   2:缓存空值 

         如果一个查询返回的数据为空(不管是数据不 存在,还是系统故障)我们仍然把这个空结果进行 缓存,但它的过期时间会很短,最长不超过五分钟。 通过这个直接设置的默认值存放到缓存, 这样第二次到缓冲中获取就有值了,而不会继续访问数据库 

缓存的收益和成本 

缓存带来的回报 :

1:高速读写   缓存加速读写速度:CPU L1/L2/L3 Cache、Linux page Cache加速硬盘读写、浏览器缓存、 Ehcache缓存数据库结果

2:降低后端负载   后端服务器通过前端缓存降低负载: 业务端使用Redis降低后端MySQL负载等 缓存带来的代价 :

1:数据不一致    缓存层和数据层有时间窗口不一致,和更新策略有关

2:代码维护成本   原本只需要读写MySQL就能实现功能,但加入了缓存之后就要去维护缓存的数据,增加了代码复杂度。 堆内缓存可能带来内存溢出的风险影响用户进程,如ehCache、loadingCache 

堆内缓存和远程服务器缓存redis的选择 :

     堆内缓存一般性能更好,远程缓存需要套接字传输

     用户级别缓存尽量采用远程缓存

     大数据量尽量采用远程缓存,服务节点化原则

redis作为数据库和作为内存缓存的两种使用方法 

redis作为数据库的使用有什么优缺点

优点 :没有Scheme约束,数据结构的变更相对容易,一开始确定数据类型, 抗压能力强,性能极 高,10万/qps 

缺点:没有索引,没有外键,缺少int/date等基本数据类型,多条件查询需要通过集合内联 (sinter,zinterstore) 和连接间接实现开发效率低,可维护性不佳 

redis作为缓存的使用,搭配数据库使用的两种方案 

jedis整合使用方案 set key,value ["11","22"] 第一层在缓存进行查询,如果得到数据则直接返回, 第二 层在数据库进行查询,并且刷新缓存,方便下次查询 ["33,"44"] 作为mybatis/hibernate二级缓存使用方案,一级缓存:sqlSession,进程缓存,单次链接有效 

事务隔离机制
语法:set global transaction isolation level read uncommitted; 

种类:read uncommitted、read committed、repeatable read、serializable 

发布了50 篇原创文章 · 获赞 2 · 访问量 2323

猜你喜欢

转载自blog.csdn.net/eafun_888/article/details/96565804