zoukankan      html  css  js  c++  java
  • Redis

    1. 为啥在项目里要用缓存呢

    用缓存,主要是俩用途,高性能和高并发

    高性能

    image.png
    image.png

    高并发
    image.png
    image.png

    2.介绍

    Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API的非关系型数据库。

    传统数据库(关系型数据库)遵循 ACID 规则。而 Nosql(非关系型数据库)(Not Only SQL 的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称) 一般为分布式,而分布式一般遵循 CAP 定理。

    CAP理论

    C:consistency(一致性)
    A:avalibility(可用性)
    P:Partition(分区)-tolerence to partition(分区容忍度)
    分区:一个分布式系统,网络不通讯,导致连接不通,系统被分割成几个数据区域
    原因:数据不连通了,产生数据分区

    影响:
    查还好一点
    数据修改时,必须要求数据一致--加锁,实现数据一致性【需求要求数据一致性】
    数据修改时,可以数据不一致--不用加锁【需求不要求数据一致性】

    分区容忍度
    数据的一致性要求高,容忍度高,加锁
    数据的一致性要求低,容忍度低,可以不加锁
    预期结果,保持数据的一致

    可用性

    请求在一定时间段内都应该有响应
    为了解决锁一直加着
    CP理论:【一致性+分区】数据的一致性要求高-加锁
    AP理论:【可用性+分区】数据的一致性要求低-不加锁

    CAP总结
    分区是常态,可不避免,三者不可共存
    可用性和一致性是一对冤家
    一致性高,可用性低
    一致性低,可用性高

    3. 为什么说redis能够快速执行

    1. 绝大部分请求是纯粹的内存操作(非常快速)
    2. 采用单线程,避免了不必要的上下文切换和竞争条件
    3. 非阻塞IO - IO多路复用

    4. Redis支持的数据类型?

    String字符串:
    格式: set key value
    string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
    string类型是Redis最基本的数据类型,一个键最大能存储512MB。

    Hash(哈希)
    key=150
    value={
    “id”: 150,
    “name”: “zhangsan”,
    “age”: 20
    }
    hash类的数据结构,主要是用来存放一些对象,把一些简单的对象给缓存起来,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值
    格式: hmset name key1 value1 key2 value2
    Redis hash 是一个键值(key=>value)对集合。
    Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

    List(列表)
    key=某大v
    value=[zhangsan, lisi, wangwu]
    比如可以通过list存储一些列表型的数据结构,类似粉丝列表了、文章的评论列表了之类的东西
    Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
    格式: lpush name value
    在 key 对应 list 的头部添加字符串元素
    格式: rpush name value
    在 key 对应 list 的尾部添加字符串元素
    格式: lrem name index
    key 对应 list 中删除 count 个和 value 相同的元素
    格式: llen name
    返回 key 对应 list 的长度
    Set(集合)
    可以基于set玩儿交集、并集、差集的操作,比如交集吧,可以把两个人的粉丝列表整一个交集,看看俩人的共同好友是谁
    格式: sadd name value
    Redis的Set是string类型的无序集合。
    集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

    zset(sorted set:有序集合)

    格式: zadd name score value
    Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
    不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
    zset的成员是唯一的,但分数(score)却可以重复。
    比如说你要是想根据时间对数据排序,那么可以写入进去的时候用某个时间作为分数,人家自动给你按照时间排序了
    排行榜:将每个用户以及其对应的什么分数写入进去,zadd board score username,接着zrevrange board 0 99,就可以获取排名前100的用户;zrank board username,可以看到用户在排行榜里的排名

    5.什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

    持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
    Redis 提供了两种持久化方式:RDB(默认) 和AOF RDB内存快照和AOF日志文件
    RDB(快照的方式):
    生成一个文件,便于复制,移动,性能比较好
    rdb是Redis DataBase缩写
    功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数
    AOF:
    Aof是Append-only file缩写
    每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作

    aof写入保存:
    WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
    SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
    存储结构:
    内容是redis通讯协议(RESP )格式的命令文本存储。
    比较:
    1、aof文件比rdb更新频率高,优先使用aof还原数据。
    2、aof比rdb更安全也更大
    3、rdb性能比aof好
    4、如果两个都配了优先加载AOF

    6. redis的底层数据结构

    redis底层有6种数据结构,分别是简单动态字符串(SDS),链表,字典,跳跃表,整数集合,压缩列表。

    跳跃表
    Redis使用跳跃表作为有序集合键的底层实现之一,若一个有序集合包含的元素数量比较多,或者有序集合中的成员是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。
    有序集合使用两种数据结构来实现,从而可以使插入和删除操作达到O(log(N))的时间复杂度。这两种数据结构是哈希表和跳跃表。向哈希表添加元素,用于将成员对象映射到分数;同时将该元素添加到跳跃表,以分数进行排序。
    和链表、字典等数据结构被广泛地应用在Redis内部不同,Redis只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群结点中用作内部数据结构。除此之外,跳跃表在Redis里面没有其他用途。
    跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表是一种随机化的数据,跳跃表以有序的方式在层次化的链表中保存元素,效率和平衡树媲美 ——查找、删除、添加等操作都可以在对数期望时间下完成,并且比起平衡树来说,跳跃表的实现要简单直观得多。
    Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另外一个是在集群节点中用作内部数据结构。

    跳跃表的定义

    image.png
    image.png

    我们先来看一下一整个跳跃表的完整结构:
         Redis 的跳跃表 主要由两部分组成:zskiplist(链表)和zskiplistNode (节点)

    7.使用redis有哪些好处?

    (1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
    (2)支持丰富数据类型,支持string,list,set,sorted set,hash
    (3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
    (4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

    8.redis的淘汰机制

    Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:
    · noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
    · allkeys-lru:在主键空间中,优先移除最近未使用的key。
    · volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
    · allkeys-random:在主键空间中,随机移除某个key。
    · volatile-random:在设置了过期时间的键空间中,随机移除某个key。
    · volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

    9.Master&Slave是什么?

    也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机
    的master/slaver机制,Master以写为主,Slave以读为主。

    它能干嘛
    1、读写分离;
    2、容灾恢复

    哨兵监控
    当master出现问题后,奖slaver切换为master

    10. redis常见性能问题和解决方案

    (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
    (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
    (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
    (4) 尽量避免在压力很大的主库上增加从库
    (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…

    这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

    11.redis包含三种集群策略

    1.主从复制: 在主从复制中,数据库分为俩类,主数据库(master)和从数据库(slave)。
    其中主从复制有如下特点:
    1.1. 主数据库可以进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库
    1.2. 从数据库一般都是只读的,并且接收主数据库同步过来的数据
    1.3. 一个master可以拥有多个slave,但是一个slave只能对应一个master、

    主从复制工作机制
    当slave启动后,主动向master发送SYNC命令。master接收到SYNC命令后在后台保存快照(RDB持久化)和缓存保存快照这 段时间的命令,然后将保存的快照文件和缓存的命令发送给slave。slave接收到快照文件和命令后加载快照文件和缓存的执行命令。

    12. Redis 有哪些架构模式?讲讲各自的特点

    单机版

    image.png
    image.png

    |

    特点:简单
    问题:
    1、内存容量有限 2、处理能力有限 3、无法高可用。

    主从复制

    image.png
    image.png

    Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。

    特点:
    1、master/slave 角色
    2、master/slave 数据相同
    3、降低 master 读压力在转交从库
    问题:
    无法保证高可用
    没有解决 master 写的压力

    哨兵

    image.png
    image.png

    Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:

    监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
    提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
    自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

    特点:
    1、保证高可用
    2、监控各个节点
    3、自动故障迁移

    缺点:主从模式,切换需要时间丢数据
    没有解决 master 写的压力

    集群(proxy 型):

    image.png
    image.png

    Twemproxy 是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器; Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。

    特点:
    1、多种 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
    2、支持失败节点自动删除
    3、后端 Sharding 分片逻辑对业务透明,业务方的读写方式和操作单个 Redis 一致

    缺点:增加了新的 proxy,需要维护其高可用。
    failover 逻辑需要自己实现,其本身不能支持故障的自动转移可扩展性差,进行扩缩容都需要手动干预

    集群(直连型):

    image.png
    image.png

    从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

    特点:
    1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
    2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
    3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
    4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
    5、实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。

    缺点:
    1、资源隔离性较差,容易出现相互影响的情况。
    2、数据通过异步复制,不保证数据的强一致性

    13. 使用过Redis分布式锁么,它是怎么实现的?

    先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
    如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
    set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

    缓存雪崩和缓存穿透问题解决方案

    缓存雪崩
    简介:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。解决办法(中华石杉老师在他的视频中提到过,视频地址在最后一个问题中有提到):
    * 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
    * 事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
    * 事后:利用 redis 持久化机制保存的数据尽快恢复缓存

    Image.jpg
    Image.jpg

    缓存穿透
    简介:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。解决办法: 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

    如何解决 Redis 的并发竞争 Key 问题

    所谓 Redis 的并发竞争 Key 的问题也就是多个系统同时对一个 key 进行操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同!
    推荐一种方案:分布式锁(zookeeper 和 redis 都可以实现分布式锁)。(如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能)
    基于zookeeper临时有序节点可以实现的分布式锁。大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。
    在实践中,当然是从以可靠性为主。所以首推Zookeeper。

    如何保证缓存与数据库双写时的数据一致性?

    你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
    一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况,最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况
    串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求。

    14. Springboot与redis的使用

    1.

    <!-- 引入redis依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    2.
    然后,资源配置文件application.yml(或properties)中加入redis相关配置:

    spring:
          redis:
            #redis数据库地址
            host: localhost
           port: 6379
            password: root
            timeout: 1000
            #redis数据库索引,默认0
           database: 1 


    3.

    这里我们引入了StringRedisTemplate类,这个类也是Java中整合Redis主要使用的操作类。这里首先使用MyBatis向数据库添加一条user数据,如果添加成功,则使用StringRedisTemplate中的opsForValue.set()方法,将该user数据Json格式化后添加到Redis数据库中,以"user : "+该user的id属性值作为键

    BoundHashOperations<StringObjectObject> hashOperations = this.stringRedisTemplate.boundHashOps(KEY_PREFIX);
    //判断是否存在此K值
    if (hashOperations.hasKey(KEY_PREFIX)) {
    hashOperations.delete(KEY_PREFIX);
    }
    seckillGoods.forEach(goods -> hashOperations.put(goods.getSkuId().toString(), goods.getStock().toString()));

    }
    redisTemplate.opsForValue().set("user : "+user.getUserId(), JsonUtils.objectToJson(user))

    redisTemplate.opsForValue().get("user : "+userId)

    15.Redis相比memcached有哪些优势?

    (1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
    (2) redis的速度比memcached快很多
    (3) redis可以持久化其数据
    (4)Redis支持数据的备份,即master-slave模式的数据备份。

  • 相关阅读:
    iOS中调用短信、电话、邮件、Safari浏览器API
    oc中的反射机制
    UIImage图片处理:缩放、设定大小、存储 (转载)
    UIView上的滑动手势及动作
    UISearchBar相关
    Kali渗透测试——利用metasploit攻击靶机WinXP SP1
    Kali渗透测试——利用metasploit攻击靶机WinXP SP1
    MATLAB求解非齐次线性方程组
    MATLAB求解非齐次线性方程组
    MATLAB测试机器零阈值的大小
  • 原文地址:https://www.cnblogs.com/wuhen8866/p/11882142.html
Copyright © 2011-2022 走看看