【初识Redis之常见问题总结】

1. 什么是Redis?说说你对Redis的了解?

Redis是一款基于键值对的NoSQL数据库,与其他键值对数据库不同的是,Redis中拥有string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、 HyperLogLog、GEO(地理信息定位)等多种数据结构。

2.Redis背后的数据结构让其拥有什么强大的功能?

  1. Redis将所有数据放到内存中的做法让它的读写性能十分惊人。

  2. Redis的持久化机制保证了在发生类似断电,机械故障等情况时,内存中的数据不会丢失。

  3. 此外Redis还提供了键过期、发布订阅、事务、流水线、Lua脚本等多个附加功能。

    总之,在合适的情况下使用Redis会大大增强系统的性能,减少开发人员工作量。

3. Redis常常使用在什么地方?Redis的应用场景有哪些?

  • 热点数据的缓存:redis访问速度块、支持的数据类型丰富,很适合用来存储热点数据。
  • 限时业务:redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。因此,Redis在限时业务中的表现很亮眼。
  • 计数器:incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成。
  • 排行榜:关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。
  • 分布式锁:这个主要利用redis的setnx命令进行,在后面的如何用Redis实现一个分布式锁中会进行详解。
  • 延时操作:redis自2.8.0之后版本提供Keyspace Notifications功能,允许客户订阅Pub/Sub频道,以便以某种方式接收影响Redis数据集的事件。
  • 分页查询、模糊查询:redis的set集合中提供了一个zrangebylex方法,通过ZRANGEBYLEX zset - + LIMIT 0 10 可以进行分页数据查询,其中- +表示获取全部数据;rangebylex key min max 这个就可以返回字典区间的数据可以利用这个特性可以进行模糊查询功能。
  • 点赞,好友等相互关系的存储:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,我们可以通过这一点实现类似共同好友等功能。
  • 队列:由于redis有list push和list pop这样的命令,所以能够很方便的执行队列操作。

4.Redis的数据类型有哪些?

Redis中拥有string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合)、Bitmaps(位图)、 HyperLogLog、GEO(地理信息定位)等多种数据结构。
Redis主要提供了5种数据结构:字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)。Redis还提供了Bitmap、HyperLogLog、Geo类型,但这些类型都是基于上述核心数据类型实现的。5.0版本中,Redis新增加了Streams数据类型,它是一个功能强大的、支持多播的、可持久化的消息队列。

  1. (字符串)sring可以存储字符串、数字和二进制数据,除了值可以是String以外,所有的键也可以是string,string最大可以存储大小为2M的数据
  2. (列表)list保证数据线性有序且元素可重复,它支持lpush、blpush、rpop、brpop等操作,可以当作简单的消息队列使用,一个list最多可以存储2^32-1个元素
  3. (哈希)hash的值本身也是一个键值对结构,最多能存储2^32-1个元素
  4. (集合)set是无序不可重复的,它支持多个set求交集、并集、差集,适合实现共同关注之类的需求,一个set最多可以存储2^32-1个元素
  5. (有序集合)zset是有序不可重复的,它通过给每个元素设置一个分数来作为排序的依据,一个zset最多可以存储2^32-1个元素。

5.各类数据结构内部的编码及结构?

每种类型支持多个编码,每一种编码采取一个特殊的结构来实现 :

  1. string:编码分为int、embstr、raw;
    int底层实现为long,当数据为整数型并且可以用long类型表示时可以用long存储;
    embstr底层实现为占一块内存的SDS结构,当数据为长度不超过32字节的字符串时,选择以此结构连续存储元数据和值;
    raw底层实现为占两块内存的SDS,用于存储长度超过32字节的字符串数据,此时会在两块内存中分别存储元数据和值。
  2. list:编码分为ziplist、linkedlist和quicklist(3.2以前版本没有quicklist)。
    ziplist底层实现为压缩列表,当元素数量小于2且所有元素长度都小于64字节时,使用这种结构来存储;linkedlist底层实现为双端链表,当数据不符合ziplist条件时,使用这种结构存储;3.2版本之后list一般采用quicklist的快速列表结构来代替前两种。
  3. hash:编码分为ziplist、hashtable两种,
    ziplist底层实现为压缩列表,当键值对数量小于2,并且所有的键值长度都小于64字节时使用这种结构进行存储;
    hashtable底层实现为字典,当不符合压缩列表存储条件时,使用字典进行存储。
  4. set:编码分为inset和hashtable,
    intset底层实现为整数集合,当所有元素都是整数值且数量不超过2个时使用该结构存储,否则使用字典结构存储。
  5. zset:编码分为ziplist和skiplist,
    当元素数量小于128,并且每个元素长度都小于64字节时,使用ziplist压缩列表结构存储,否则使用skiplist的字典+跳表的结构存储。

6.Redis数据类型中zset,它和set有什么区别?底层是怎么实现的?

(有序集合)zset和(集合)set,一样也是 string 类型元素的集合,且不允许重复的成员。
(有序集合)zset中的每个元素都会关联一个 double 类型的分数,Redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合(zset)的成员是唯一的,但分数 ( score ) 却可以重复。
(集合)set是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中最大的成员数为 2^32 – 1 ( 4294967295 ) , 每个集合可存储 40 多亿个成员。
(有序集合)zset底层的存储结构包括ziplist或skiplist,在同时满足有序集合保存的元素数量小于128个和有序集合保存的所有元素的长度小于64字节的时候使用ziplist,其他时候使用skiplist。 当ziplist作为zset的底层存储结构时候,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。 当skiplist作为zset的底层存储结构的时候,使用skiplist按序保存元素及分值,使用dict来保存元素和分值的映射关系。
课外拓展:
实际上单独使用Hashmap或skiplist也可以实现有序集合,Redis使用两种数据结构组合的原因是如果我们单独使用Hashmap,虽然能以O(1) 的时间复杂度查找成员的分值,但是因为Hashmap是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;而如果单独使用skiplist,虽然能执行范围操作,但查找操作的复杂度却由 O(1)变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。
7.什么是缓存穿透、缓存击穿、缓存雪崩?它们对应的解决方案是什么?

缓存穿透:是指客户端查询了根本不存在的数据,使得这个请求直达存储层,导致其负载过大甚至造成宕机。这种情况可能是由于业务层误将缓存和库中的数据删除造成的,当然也不排除有人恶意攻击,专门访问库中不存在的数据导致缓存穿透。
解决方案:
我们可以通过缓存空对象的方式布隆过滤器两种方式来解决这一问题。缓存空对象是指当存储层未命中后,仍然将空值存入缓存层 ,当客户端再次访问数据时,缓存层直接返回空值。还可以将数据存入布隆过滤器,访问缓存之前以过滤器拦截,若请求的数据不存在则直接返回空值。

缓存击穿:当一份访问量非常大的热点数据缓存失效的瞬间,大量的请求直达存储层,导致服务崩溃。
解决方案:
缓存击穿可以通过热点数据不设置过期时间来解决,这样就不会出现上述的问题,这是“物理”上的永不过期。或者为每个数据设置逻辑过期时间,当发现该数据逻辑过期时,使用单独的线程重建缓存。除了永不过期的方式,我们也可以通过加互斥锁的方式来解决缓存击穿,即对数据的访问加互斥锁,当一个线程访问该数据时,其他线程只能等待。这个线程访问过后,缓存中的数据将被重建,届时其他线程就可以直接从缓存中取值。

缓存雪崩:是指当某一时刻缓存层无法继续提供服务,导致所有的请求直达存储层,造成数据库宕机。可能是缓存中有大量数据同时过期,也可能是Redis节点发生故障,导致大量请求无法得到处理。
解决方案:
缓存雪崩的解决方式有三种;第一种是在设置过期时间时,附加一个随机数,避免大量的key同时过期。第二种是启用降级和熔断措施,即发生雪崩时,若应用访问的不是核心数据,则直接返回预定义信息/空值/错误信息。或者在发生雪崩时,对于访问缓存接口的请求,客户端并不会把请求发给Redis,而是直接返回。第三种是构建高可用的Redis服务,也就是采用哨兵或集群模式,部署多个Redis实例,这样即使个别节点宕机,依然可以保持服务的整体可用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值