redis相关

一、redis能做什么?

  1、缓存

  2、分布式锁

  3、延迟队列

二、redis基本数据结构?

  字符串string、列表list、字典hash、集合set、有序集合zset

  redis中所有的数据结构都是以唯一的key字符作为名称,然后通过这个key来获取相应的value数据,不同数据类型的差异就在于value的结构不同。

  1、字符串string

    redis中的字符串都是动态字符串,是可修改的,采用预分配冗余空间的方式来减少内存的频繁分配,内部为当前字符串分配的空间(capacity)是大于当前字符串的长度len的,当前字符串的长度小于1MB时,扩容

    都是翻倍现有的空间的。如果字符串长度大于1MB时,扩容一次只会扩大1MB,并且字符串的最大长度是512MB。

  2、列表list

    redis中的列表相当于java中的linkedlist,注意他是链表而不是数组。这也就也为着list的插入和删除操作非常快,时间复杂度为O(1),但是索引定位慢,时间复杂度为O(N)。列表中的每个元素都使用双向指针,

    穿起来可以同时支持前向后向遍历,当列表弹出最后一个元素之后,该数据结构就会被自动删除。redis列表常用来做异步队列使用,将需要延后处理的任务结构序列化常字符串,塞进redis列表,另一个线程从这个

    列表中轮询数据进行处理。

  3、字典hash

    redis中的字典相当于java中的hashMap,他是无序字典,内部存储了很多键值对,数据机构也是数据+链表的结构。Java中的rehash是个耗时的操作,需要一次性全部rehash。redis为了性能,采用的是渐进式rehahs策略

  4、集合set

    redis集合相当于java中的hashSet,他内部的键值对是无序的,唯一的,他内部实现相当于一个特殊的字典,字典中所有的value都是一个值NULL

  5、有序列表zset

    类似于java的Sortedset和hashmap的结合体,一方面是一个set,保证内部value的唯一性,另一方面他可以给每个value赋予一个score,代表这个value的权重,它内部实现用的是一种叫跳跃列表的数据结构。

  高级数据结构:

  heperloglog:用来解决统计问题的数据结构(不精确,标准误差在0.81%)

  BloomFilter(布隆过滤器):可以理解为不精确的set结构,当使用它的contains方法判断某个对象是否存在是,他可能会存在误判

  geohash(地理位置)

 

三、分布式锁

  分布式应用在进行逻辑处理时经常会遇到并发问题。

  分布式锁本质上要实现的目标就是在redis中占一个“坑”,当别的进程也要来占时,发现已经被占用时,就只好放弃或者稍后再试。占坑一般使用的setnx(set if not exists)指令,只允许被一个客户占用,先来先用,用完了,

  在调用del指令释放坑。

  一般会有一个问题,当锁定坑后,处理业务逻辑异常,可能导致del命令没有被调用,这样就会陷入死锁,锁得不到释放,因此,一般在拿到锁后,会给锁加一个过期时间,这样即使出现异常也不会出现锁被永远占用的情况

  (上边这个解决方式仍然会有问题,当在设置过期时间时,如果因为网络问题导致expire命令没有执行,这样仍然会出现锁一直得不到释放的情况,解决方式,使用第三方库,或者使用redis2.8之后的版本,2.8之后set指令中加

  了扩展参数,可以设置过期时间,这样setnx和expire两个指令就可以一起执行了)

 分布式锁超时问题:

  redis的分布式锁不能解决超时问题,如果加锁和解锁中间的业务流程耗时过长,大于锁的过期时间时,这样就会出现问题。

 

四、延迟队列

  相对于专业的Rabbitmap或者kafka等消息队列中间节,redis针对只有一组消费者的情况来说可以简化很多操作(中间件各种操作过多,代码繁杂,如果对消息可靠性要求不高的话,可以使用redis来作为消息中间件)。

  通过redis中的列表list来实现,list常用来作为异步的消息队列来使用,用rpush和lpush来操作入队,使用rpop和lpop来操作出队。它可以支持多个生产这和多个消费者并发进出消息,每个消费者拿到的消息都是不同的列表元素。

  问题:

  1、如果list空了怎么处理?

  list空了之后,调用pop指令会陷入死循环,不同的pop,并且没有数据,产生空轮询,增大cup消耗,降低redis的QPS 

    解决:可以使用sleep睡眠以下,但是该方式也不适合,另一种方式就是使用阻塞读blpop/brpop,b代表的就是blocking

  2、阻塞读之后,可能会产生空闲链接的问题?

  如果在阻塞读时,列表中一直没有数据,线程就会一直阻塞,redis的客户端链接就变成了空闲链接,闲置过久,服务器一般就会主动断开链接,减少闲置资源的占用,这时候brpop/blpop指令就会抛出异常,因此,再使用阻塞读

  时,一定要进行try/catch捕获异常,并且还要进行重试。

 

五、位图

  在平时开发过程中,会有一些boolean类型的数据要存储,例如一个用户一年的签到记录,签了是1,没签是0,要记录365天,如果使用普通的key/value,没有用户就要记录365个,当用户上亿时,需要的存储空间就非常大了。

  为了解决这个问题,redis提供了位图数据结构,这样每天的签到记录只会占用365个位,也就是46个字节(一个稍长的字符串)就可以完全容纳下,位图最小单位是bit,每个bit的取值只能是0或者1

  位图不是一种特殊的数据结构,让的内容其实就是普通的字符串,也就是byte数组,我们可以使用普通的get/set来操作位图,也可以使用getbit/setbit等将位图看成数组来操作。

  位图相关指令:

  getbit/setbit/bitcount/bitpos

  bitcount:统计指定位置范围内容1的个数

  bitpos:查找指定范围内出现的第一个0或者1

 

六、redis的io模型

  redis是个单线程程序

  问题:

  redis是单线程,为什么还那么快?

    redis所有的数据都在内存中,所有的运算都是内存级别的运算

  为什么能够处理那么多的并发客户端连接?

    io的多路复用,select系列的时间轮询api,非阻塞io

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

巡山小妖008

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

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

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

打赏作者

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

抵扣说明:

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

余额充值