redis简介

数据存储的结构类型:

  String, List, Set, ZSet(Sorted Set:有序集合), Hash五种数据结构的存储

 
特点:
  开源,ANSI语言,C语言,BSD协议,支持网络,可持久化日志型,键值对类型.它通常被称为数据结构服务器
 
持久化数据:
    Redis持久化类型:
    持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
        RDB(Redis DataBase)和AOF(Append-only file)
    Redis通讯协议:
        内容是redis通讯协议(RESP)格式的命令文本存储。
 
Redis通讯协议(RESP):
    RESP(BS协议): 客户端和服务端之前使用的一种通讯协议
    RESP的特点:   实现简单、快速解析、可读性好
 
Redis架构特点:
    单机版:
        特点:简单
        缺点:内存容量有限,处理能力有限,无法高可用。
    主从复制:
        特点:只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据降低master读压力(转移至从库),master/slave角色,主从数据相同
        缺点:无法保证高可用,没有解决master写的压力
    哨兵:
        特点:在主服务器下线时自动进行故障转移(监控,提醒,自动故障迁移)[保证高可用]
        缺点:主从模式,切换主从时需要的时间段内会丢数据
    集群(proxy型):
        Twemproxy是一个Twitter开源的一个redis和memcache快速/轻量级代理服务器;
        Twemproxy是一个快速的单线程代理程序,支持Memcached ASCII协议和redis协议。
        特点:1.多种 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
                2.支持失败节点自动删除
                3.后端Sharding分片逻辑对业务透明
        缺点:增加了新的 proxy,需要维护其高可用。(failover逻辑需要自己实现,可扩展性差)
    集群(直连型):
        从redis3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构
        特点:1.数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
       2.节点可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
       3.高可用性,部分节点不可用时,集群仍可用。通过增加Slave做备份数据副本
       4.实现故障自动Failover,节点之间通过 Gossip 协议交换状态信息.
       5.无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
        缺点:资源隔离性较差,容易出现相互影响的情况(数据异步复制,不保证数据的强一致性)
 
Redis常用命令:
    keys (pattern)  :查询所有key
    setnx(key value):如果key已经存在返回 0,nx 是 not exist 的意思
    setex(key seconds value):将值value关联到key,并将key的过期时间设为seconds(以秒为单位)。
    expire mset getset(返回oldValue,没有就返回nil)
    persist(key):取消过期时间
    ... ...
 
Redis配置异步队列:
    使用redis里的list或者set数据结构,rpush生产消息,lpop消费消息。(先入先出原则)
    在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitMQ等。
    问题:
        ①生产者速度大于消费者消费速度,消息队列长度会一直增大,时间久了会占用大量内存空间。
        ②睡眠时间过长,这样不能处理一些时效性的消息,睡眠时间过短,也会在连接上造成比较大的开销。
    解决方案:brpop和blpop实现阻塞读取
 
Redis的订阅/消费:
    服务端可以使用publish去推送消息,客服端使用subscribe去消费
    订阅的时候subscribe()和psubscribe()的第二个参数支持可变参数,也就是可以实现订阅多个频道。要注意的是,订阅获得的内容(三部分:信息类型如"message",信息频道如channel1:1,信息主体如内容)
    重写JedisPubSub 的onPMessage方法,可以将message直接区分后获取
    发布订阅执行订阅之后该线程处于阻塞状态,线程不会终止,如果终止线程需要退订,需要调用JedisPubSub的unsubscribe()方法
 
缓存穿透和雪崩:
    如果对数据的一致性要求很高,那么就不能使用缓存
    缓存穿透:传统方法是先查询缓存,若是不存在,则去查DB,若是DB也不存在,则不作缓存(攻击者会不断查询一个不存在的key,从而对数据库造成很大的压力)
    解决方法1:对数据库不存在的数据,也提供一个缓存,并设置短期的过期时间,如30s
    解决方法2:布隆过滤器,将所有可能存在一个bitmap中进行过滤(就不会去查不存在的数据)
 
    缓存雪崩1号:大批量数据在同一时间端内,缓存同时失效(如双十一的商品信息缓存)
    解决方法:不同分类商品,缓存不同周期。(即在时间周期后补加一个random时间)
 
    缓存雪崩2号:缓存服务器某个节点宕机或断网(严重)
    解释:自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么那个时候数据库能顶住压力,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
 
    缓存击穿:是指一个key非常热点,在不停的扛着大并发,在某一时刻key失效
    解决方法:"爆款"商品key永不过期(不需要使用mutex_key互斥锁)
 
mutex_key互斥锁(针对缓存穿透):
 1 public String get(key) {
 2       String value = redis.get(key);
 3       if (value == null) { //代表缓存值过期
 4           //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
 5           if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
 6                value = db.get(key);
 7                       redis.set(key, value, expire_secs);
 8                       redis.del(key_mutex);
 9               } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
10                       sleep(50);
11                       get(key);  //重试
12               }
13           } else {
14               return value;      
15           }
16  }

 

 
 
redis菜鸟教程: https://www.runoob.com/redis/redis-tutorial.html
redis常见面试题: https://www.cnblogs.com/jasontec/p/9699242.html
redis缓存问题: https://blog.csdn.net/zeb_perfect/article/details/54135506
 
 
posted @ 2019-07-29 18:30  CrazyMiniCat  阅读(103)  评论(0)    收藏  举报