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

KEYS pattern:查找所有符合给定模式pattern的key

  keys指令一次返回所有匹配的key

  键的数量过大则会造成服务卡顿

*从海量key里查询出某一固定前缀的key: SCAN cursor [MATCH pattern][COUNT count]

  基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程,以0作为游标开始一次新的迭代,知道命令返回游标0完成一次遍历。不保证每次执行都返回某个给定数量的元素,支持模糊查询。一次返回的数量不可控,只能大概率符合count参数

  第一次scan:  scan 0 match k1* count 10   :从0开始迭代,符合k1前缀的字符串,数量为10.

  第二次scan:    scan 11534336 k1* count 10

     多次scan可能获取到重复的数据

 分布式锁需要解决的问题:1、互斥性 2、安全性 3、死锁 4、容错

如何通过redis实现分布式锁:

  SETNX key value:如果key不存在,则创建并赋值。

  时间复杂度:O(1),返回值:设置成功返回1,失败返回0

   

如何解决SETNX长期有效的问题?

  设置过期时间:EXPIER  key seconds:设置key的生存时间,当key过期时,会自动删除

  

以上代码的风险:当设置锁成功后,在执行if判断前,服务宕机(即没有设置过期时间),产生的原因:原子性得不到满足

redis新版本set的时候可以设置过期时间(实现了原子性)

SET key value [EX seconds] [PX milliseconds] [NX|XX] :

  EX seconds:设置键的过期时间为seconds秒

  PX milliseconds:设置过期时间毫秒值

  NX: 只在键不存在时,才对建进行设置操作

  XX:只在键已经存在时,才对键进行设置操作

  SET:操作成功完成时,返回OK,否则返回nil

set lockid 1234 ex 10 nx

 大量的key同时过期时注意的事项:

  在设置过期的时候,给每个key减伤随机值

分布式锁的删除:

```java

public static boolean releaseLock(String key, String uniqueId) {
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) else return 0 end";
return jedis.eval(
luaScript,
Collections.singletonList(key),
Collections.singletonList(uniqueId)
).equals(1L);
}

```

原文地址:https://www.cnblogs.com/nxzblogs/p/11260622.html