美文网首页
Redis知识整理

Redis知识整理

作者: gregocean | 来源:发表于2019-05-12 14:43 被阅读0次

    价值与场景

    Redis 这么火,它都解决了哪些问题?
    问题场景:接口慢
    方案1:消费者端缓存(cache-control:max-age)——旧数据,依然有大量新请求
    方案2:基于本机内存的1分钟缓存——旧数据,单机内存不够
    方案3:Redis单机服务器——挂了就缓存丢失、造成重启和恢复中的雪崩
    方案4:Redis持久化——缓解重启时的大量重新请求
    方案5:Sentinel和Replication——缓解Redis挂了的问题

    • Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的功能;是对Redis的发布和订阅功能的一个利用。
    • Replication则是负责让一个Redis服务器可以配备多个备份的服务器。Redis也是利用这两个功能来保证Redis的高可用的。

    方案6:集群——解决单机资源有限问题

    • Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
    • Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

    常用数据结构

    String,Hash,List,Set,Sorted Set
    https://my.oschina.net/xsh1208/blog/2218494

    • String
      可变的字节数组
      会多分配空间字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间
    # get set strlen 
    # getrange 获取子串
    # setrange 设置子串
    # append 追加
    # 没有删除子串,和插入子串
    
    # 计数器
    > set ireader 42
    OK
    > get ireader
    "42"
    > incrby ireader 100
    (integer) 142
    > get ireader
    "142"
    > decrby ireader 100
    (integer) 42
    > get ireader
    "42"
    > incr ireader  # 等价于incrby ireader 1
    (integer) 143
    > decr ireader  # 等价于decrby ireader 1
    (integer) 142
    
    > expire ireader 60
    (integer) 1  # 1表示设置成功,0表示变量ireader不存在
    > ttl ireader
    (integer) 50  # 还有50秒的寿命,返回-2表示变量不存在,-1表示没有设置过期时间
    > del ireader
    (integer) 1  # 删除成功返回1
    > get ireader
    (nil)  # 变量ireader没有了
    
    • list
      双向链表实现(数据量少是ziplist,数据量大是quicklist(把连续的内存空间(ziplist)连起来而非对每个元素都用指针连,后者太费空间))。可用作队列、堆栈
    rpush
    rpop
    lpush
    lpop
    llen
    lset
    lrange
    linsert xxx before a b# linsert指令并不是通过指定位置来插入,而是通过指定具体的值
    lrem l_name n object# 删除
    blpop # 阻塞pop
    lindex # 随机读
    
    • hash
      和Java的HashMap数据结构一致
    # 增加元素
    > hset ireader go fast
    > hmset ireader java fast python slow # 添加多个
    # 获取元素
    > hmset ireader go fast java fast python slow
    OK
    > hget ireader go
    "fast"
    > hmget ireader go python
    1) "fast"
    2) "slow"
    > hgetall ireader
    1) "go"
    2) "fast"
    3) "java"
    4) "fast"
    5) "python"
    6) "slow"
    > hkeys ireader
    1) "go"
    2) "java"
    3) "python"
    > hvals ireader
    1) "fast"
    2) "fast"
    3) "slow"
    #删除元素
    > hmset ireader go fast java fast python slow
    OK
    > hdel ireader go
    (integer) 1
    > hdel ireader java python
    (integer) 2
    # 是否存在
    > hexists ireader go
    (integer) 1
    

    hash也可做计数器

    • Set
      Java的HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构
    > sadd ireader go java python # 插入
    (integer) 3
    # 读取
    > smembers ireader
    1) "java"
    2) "python"
    3) "go"
    > scard ireader
    (integer) 3
    > srandmember ireader
    "java"
    # 删除
    > sadd ireader go java python rust erlang
    (integer) 5
    > srem ireader go java
    (integer) 2
    > spop ireader
    "erlang"
    # 元素是否存在
    > sismember ireader rust
    (integer) 1
    > sismember ireader javascript
    (integer) 0
    
    • ZSet(SortedSet)

    SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。

    zset底层实现使用了两个数据结构,第一个是hash,第二个是跳跃列表,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。跳跃列表的目的在于给元素value排序,根据score的范围获取元素列表。

    # 增加1-N个value/score对
    > zadd ireader 4.0 python
    (integer) 1
    > zadd ireader 4.0 java 1.0 go
    (integer) 2
    # 获取排名
    > zscore ireader python
    "5"
    > zrank ireader go  # 分数低的排名考前,rank值小
    (integer) 0
    > zrank ireader java
    (integer) 1
    > zrank ireader python
    (integer) 2
    > zrevrank ireader python
    (integer) 0
    # 操作很多,不一一列举
    

    跳表很重要!

    高级数据结构

    https://blog.csdn.net/wufaliang003/article/details/82016385

    • Bitmaps
    127.0.0.1:6380> setbit dupcheck 10 1
    (integer) 0
    127.0.0.1:6380> getbit dupcheck 10 
    (integer) 1
    
    • Hyperloglogs
      涉及数学,不太理解
    • GEO
      地理位置信息,经纬度
    • Pub/Sub主题订阅者模式
      实现1对N的消息订阅
      缺点:消费者下线的情况下,生产的消息会丢失,要用专业的消息队列如rabbitmq等。

    底层数据结构

    进阶

    Redis Module
    1.BloomFilter
    2.RedisSearch
    3.Redis-ML

    分布式锁

    先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。

    • 如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
      这个锁就永远得不到释放了。set指令有非常复杂的参数,是可以同时把setnx和expire合成一条指令来用.

    核心原理与源码分析

    http://zhangtielei.com/posts/blog-redis-how-to-start.html

    • Redis的事件循环(Event Loop)的机制,关系到:

    为什么Redis是单线程执行却能同时处理多个请求?(当然严格来说Redis运行起来并非只有一个线程,但除了主线程之外,Redis的其它线程只是起辅助作用,它们是一些在后台运行做异步耗时任务的线程)

    Redis的main函数开始执行后的逻辑可以分为两个阶段:
    1.各种初始化(包括事件循环的初始化);
    2.执行事件循环。

    image.png

    这几个部分也很重要,有时间再细细了解

    1. 持久化
    2. PipeLine
    3. 同步机制

    底层数据结构:
    https://www.cnblogs.com/ysocean/p/9080942.html

    相关文章

      网友评论

          本文标题:Redis知识整理

          本文链接:https://www.haomeiwen.com/subject/ylhvnqtx.html