关于大数据:Redis轻松实现秒杀系统

41次阅读

共计 17120 个字符,预计需要花费 43 分钟才能阅读完成。

本文章转自:乐字节
文章次要解说:Redis
获取更多 Java 相干材料能够关注公众号《乐字节》发送:999

缓存 Cache

缓存的概念

  • 缓存是存储在计算机上的一个原始数据复制集,以便于拜访。

  • Web 我的项目常见的缓存场景

缓存击穿

  • 概念:

    • 对于一些设置了过期工夫的 key,如果这些 key 可能会在某些工夫点被超高并发地拜访,是一种十分“热点”的数据
  • 起因:

    • 缓存在某个工夫点过期的时候,恰好在这个工夫点对这个 Key 有大量的并发申请过去,该 key 没有命中,大量申请穿透到数据库服务器
  • 解决方案:

    • 对于热点数据,慎重考虑过期工夫,确保热点期间 key 不会过期,甚至有些能够设置永不过期。
    • 应用互斥锁(比方 Java 的多线程锁机制),第一个线程拜访 key 的时候就锁住,等查询数据库返回后,把值插入到缓存后再开释锁

缓存雪崩

  • 概念:

    • 大量的 key 设置了雷同的过期工夫,导致在缓存在同一时刻全副生效,造成刹时 DB 申请量大、压力骤增,引起雪崩。
    • 缓存服务器宕机,也算做缓存雪崩。
  • 起因:大量缓存在同一时间生效;大量申请落到后端 DB 上;
  • 解决方案:

    • 不同的 key,设置不同的过期工夫(随机值),让缓存生效的工夫点尽量平均;
    • 应用高可用的分布式缓存集群,确保缓存的高可用性

      • 做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 生效时,能够拜访 A2。

缓存穿透

  • 概念:

    • 拜访一个肯定不存在的 key,缓存不起作用,申请会穿透到 DB,流量大时 DB 会挂掉
    • 起因:key 被高并发拜访;该 key 没有命中,去后端 DB 获取;大量申请穿透到数据库服务器
    • 解决方案:

      • 布隆过滤器,

        • 应用一个足够大的 bitmap,用于存储可能拜访的 key,不存在的 key 间接被过滤,防止对底层数据存储系统造成压力;
      • 拜访 key 未在 DB 查问到值,也将空值写进缓存,但能够设置较短过期工夫

缓存一致性

  • 概念:

    • 当数据时效性要求很高时,须要保障缓存中的数据与数据库中的保持一致,须要保障缓存节点和正本中的数据也保持一致,不能呈现差别景象。(集群同步)
  • 起因:

    • 对同一个数据进行读写,在数据库层面并发的读写并不能保障实现程序;
    • 产生了写申请 A,A 的第一步淘汰了 cache;A 的第二步写数据库,收回批改申请;
    • 产生了读申请 B,B 的第一步读取 cache,发现 cache 中是空的;B 的第二步读取数据库,收回读取申请,
    • 如果 A 的第二步写数据还没实现,读出了一个脏数据放入 cache;
  • 解决方案:

    • 个别会在数据产生更改的时,被动更新缓存中的数据或者移除对应的缓存。

Redis 的介绍

官网

  • http://www.redis.cn/
  • https://redis.io/

Redis 简介

Redis 是一个开源(BSD 许可)的,内存 中的数据结构存储系统,它能够用作 数据库、缓存和消息中间件 。它反对多种类型的数据结构,如 字符串(strings) 散列(hashes)列表(lists)汇合(sets)有序汇合(sorted sets) 与范畴查问,bitmaps,hyperloglogs 和 天文空间(geospatial)索引半径查问。Redis 内置了复制(replication),LUA 脚本(Lua scripting),LRU 驱动事件(LRU eviction),事务(transactions)和不同级别的 磁盘长久化(persistence),并通过Redis 哨兵(Sentinel) 和主动分区(Cluster)提供高可用性(high availability)

Redis 性能

上面是官网的 bench-mark 数据:

测试实现了 50 个并发执行 100000 个申请。设置和获取的值是一个 256 字节字符串。

后果: 读的速度是 110000 次 /s, 写的速度是 81000 次 /s

Redis 历史简介

2008 年,意大利一家守业公司 Merzia 的创始人 Salvatore Sanfilippo 为了防止 MySQL 的低性能,亲自定做一个数据库,并于 2009 年开发实现,这个就是 Redis。

从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。

从 2013 年 5 月开始,Redis 的开发由 Pivotal 资助。

​ 阐明:Pivotal 公司是由 EMC 和 VMware 联结成立的一家新公司Pivotal 心愿为新一代的利用提供一个原生的根底,建设在具备领导力的云和网络公司一直转型的 IT 个性之上。Pivotal 的使命是推广这些翻新,提供给企业 IT 架构师和独立软件提供商。

反对语言

反对的数据类型

stringhashlistsetsorted set

Redis 的装置(SingleNode)

装置依赖

yum -y install gcc-c++ autoconf automake

下载并上传

解压

tar zxvf redis-5.0.3.tar.gz

预编译和装置

切换到解压目录

cd redis-5.0.3/
## 编译源代码
make MALLOC=libc
## 创立 redis 的装置目录
mkdir -p /opt/lzj/redis
## 如果须要指定装置门路,须要增加 PREFIX 参数 **
make PREFIX=/opt/lzj/redis/ install

Redis-cli: 客户端

Redis-server: 服务器端

前台启动

##redis 服务默认端口号为 6379
./redis-server

后盾启动

  • 复制 redis.conf 至装置门路下

    • ## 创立一个配置文件目录
      mkdir -p /opt/lzj/redis/conf
      ## 拷贝配置文件到目录中
  • 批改装置门路下的 redis.conf,将 daemonize 批改为 yes

  • 启动时,指定配置文件门路即可

    windows 客户端拜访

    装置 Redis 客户端

    批改配置文件 redis.conf

    正文掉 bind 127.0.0.1 能够使所有的 ip 拜访 redis,若是想指定多个 ip 拜访,但并不是全副的 ip 拜访,能够 bind 设置

    敞开保护模式,批改为 no

    增加拜访认证

    咱们能够批改默认数据库的数量 默认 16, 批改 database 32 则默认为 32 个数据库

    批改后 kill -9 XXXX 杀死 redis 过程,重启 redis

    再次建设连贯 -> 胜利

    <img src=”https://i0.hdslb.com/bfs/album/ac98020a966ed38c74b3d5e295efa5d46e59c7aa.png” alt=”image-20200717111412879″ style=”zoom: 80%;” />

    Redis 的命令

    Redis-cli 连贯 Redis

    -h: 用于指定 ip

    -p: 用于指定端口

    -a: 用于指定认证明码

    PING 命令返回 PONG

    指定 database

    Redis-cli 操作 Redis

    操作 Key

    exists 查问 key 是否存在

    keys 查问是否存在指定的 key

    type 查问 key 的数据类型

    scan 扫描以后库中所有的 key

    操作 String

    set: 增加一条 String 类型数据

    get: 获取一条 String 类型数据

    mset: 增加多条 String 类型数据

    mget: 获取多条 String 类型数据

    incr: 在 value 根底上加 1

    decr:在 value 根底上减 1

    操作 hash

    hset: 增加一条 hash 类型数据

    hget: 获取一条 hash 类型数据

    hmset: 增加多条 hash 类型数据

    hmget: 获取多条 hash 类型数据

    hgetAll: 获取指定所有 hash 类型数据

    hdel: 删除指定 hash 类型数据(一条或多条)

    操作 list

    lpush: 左增加(头)list 类型数据

    rpush: 右增加 (尾) 类型数据

    lrange: 获取 list 类型数据 start 起始下标 end 完结下标 蕴含关系

    llen: 获取条数

    lrem: 删除列表中几个指定 list 类型数据

    lrem key count value 
    count > 0   从前向后删除 count 个 value
    count <0    从后向前删除  绝对值(count)个 value
    count = 0   删除所有的 value

    操作 set

    sadd: 增加 set 类型数据

    smembers: 获取 set 类型数据

    scard: 获取条数

    srem: 删除数据

    操作 sorted set

    sorted set 是通过分数值来进行排序的,分数值越大,越靠后。

    zadd: 增加 sorted set 类型数据

    zrange: 获取 sorted set 类型数据

    zcard: 获取条数

    zrem: 删除数据

    zadd 须要将 Float 或者 Double 类型分数值参数,搁置在值参数之前

    zscore|ZINCRBY:ZINCRBY key increment member 为有序集 key 的成员 member 的 score 值加上增量 increment

    操作 namespace

    操作生效工夫

    Redis 有四个不同的命令能够用于设置键的生存工夫 (键能够存在多久) 或过期工夫(键什么时候会被删除) :

    EXPlRE <key> <ttl> : 用于将键 key 的生存工夫设置为 ttl 秒。

    PEXPIRE <key> <ttl>: 用于将键 key 的生存工夫设置为ttl` 毫秒。

    EXPIREAT <key> < timestamp>: 用于将键 key 的过期工夫设置为 timestamp 所指定的秒数工夫戳。

    PEXPIREAT <key> < timestamp > : 用于将键 key 的过期工夫设置为 timestamp 所指定的毫秒数工夫戳。

    TTL: 获取的值为 - 1 阐明此 key 没有设置有效期,当值为 - 2 时证实过了有效期。

    办法一

    办法二

    办法三

    第一个参数:key

    第二个参数:value

    第三个参数:

    NX是 key 不存在时才 set,避免笼罩

    XX是 key 存在时才 set,不创立新的 key

    第四个参数:EX是秒,PX是毫秒

    删除

    del: 用于删除数据(通用,实用于所有数据类型)

    hdel: 用于删除 hash 类型数据

    Redis 的事务机制

    Redis 事务是一个独自的隔离操作:事务中的所有命令都会序列化、按程序地执行。事务在执行的过程中,不会被其余客户端发送来的命令申请所打断。
    Redis 事务的次要作用就是串联多个命令避免别的命令插队

  • Multi、Exec、discard

    • 输出 Multi 命令开始,输出的命令都会顺次进入命令队列中,但不会执行,
    • 输出 Exec 后,Redis 会将之前的命令队列中的命令顺次执行。
    • 组队的过程中能够通过 discard 来放弃组队、
  • 事务的错误处理

    • 组队阶段 某个命令呈现了报告谬误,执行时整个的所有队列会都会被勾销。
    • 执行阶段 某个命令报出了谬误,则只有报错的命令不会被执行,而其余的命令都会执行,不会回滚。
  • 事务锁的机制

    • 乐观锁
    • 乐观锁
    • Redis 就是利用这种 check-and-set 机制实现事务的

    数据的长久化

    ​ redis 是一个内存数据库,数据保留在内存中,尽管内存的数据读取速度快,然而很容易产生失落。Redis 还为咱们提供了长久化的机制,别离是 RDB(Redis DataBase)和 AOF(Append Only File)

    RDB(Redis DataBase)

  • RDB 长久化能够在指定的工夫距离内生成数据集的工夫点快照,这是默认的长久化形式
  • 这种形式是就是将内存中数据以快照的形式写入到二进制文件中, 默认的文件名为 dump.rdb
  • RDB 提供了三种触发机制:save、bgsave、自动化

    • save 触发形式

      • 该命令会阻塞以后 Redis 服务器,执行 save 命令期间,Redis 不能解决其余命令,直到 RDB 过程实现为止。
    • bgsave 触发模式

      • 执行该命令时,Redis 会在后盾异步进行快照操作,快照同时还能够响应客户端申请。
      • Redis 过程执行 fork 操作创立子过程,RDB 长久化过程由子过程负责,实现后主动完结。阻塞只产生在 fork 阶段,个别工夫很短。
    • 主动触发

      • 主动触发是由咱们的配置文件来实现的。
      • # 配置文件
        #   after 900 sec (15 min) if at least 1 key changed
        #   after 300 sec (5 min) if at least 10 keys changed
        #   after 60 sec if at least 10000 keys changed
        save 900 1
        save 300 10
        save 60 10000
        
        #配置文件的意义
        服务器在 900 秒之内,对数据库进行了至多 1 次批改
        服务器在 300 秒之内,对数据库进行了至多 10 次批改
        服务器在 60 秒之内,对数据库进行了至多 10000 次批改
      • stop-writes-on-bgsave-error
      • # However if you have setup your proper monitoring of the Redis server
        # and persistence, you may want to disable this feature so that Redis will
        # continue to work as usual even if there are problems with disk,
        # permissions, and so forth.
        # 默认值为 yes。当启用了 RDB 且最初一次后盾保留数据失败,Redis 是否进行接收数据。stop-writes-on-bgsave-error yes
      • rdbcompression
      • # Compress string objects using LZF when dump .rdb databases?
        # For default that's set to'yes'as it's almost always a win.
        # If you want to save some CPU in the saving child set it to 'no' but
        # the dataset will likely be bigger if you have compressible values or keys.
        # 默认值是 yes。对于存储到磁盘中的快照,能够设置是否进行压缩存储。rdbcompression yes
      • rdbchecksum
      • # RDB files created with checksum disabled have a checksum of zero that will
        # tell the loading code to skip the check.
        # 默认值是 yes。在存储快照后,咱们还能够让 redis 应用 CRC64 算法来进行数据校验,然而这样做会减少大概 10% 的性能耗费
        rdbchecksum yes
      • dbfilename
      • # The filename where to dump the DB
        # 设置快照的文件名,默认是 dump.rdb
        dbfilename dump.rdb
      • dir
      • # The working directory.
        # The DB will be written inside this directory, with the filename specified
        # above using the 'dbfilename' configuration directive.
        # The Append Only File will also be created inside this directory.
        # Note that you must specify a directory here, not a file name.
        # 设置快照文件的寄存门路,这个配置项肯定是个目录,而不能是文件名
        dir ./
  • RDB 的劣势和劣势

    • 劣势:

      • RDB 文件紧凑,全量备份,非常适合用于进行备份和劫难复原。
      • 生成 RDB 文件的时候,redis 主过程会 fork()一个子过程来解决所有保留工作,主过程不须要进行任何磁盘 IO 操作
      • RDB 在复原大数据集时的速度比 AOF 的复原速度要快。
    • 劣势

      • 当进行快照长久化时,会开启一个子过程专门负责快照长久化,子过程会领有父过程的内存数据,
      • 父过程批改内存子过程不会反馈进去,
      • 所以在快照长久化期间批改的数据不会被保留,可能失落数据。

    AOF(Append Only File)

  • 全量备份总是耗时的,有时候咱们提供一种更加高效的形式 AOF,工作机制很简略,redis 会将每一个收到的写命令都通过 write 函数追加到文件中。艰深的了解就是日志记录。
  • rewrite 策略

    • 重写日志,缩小日志文件的大小,redis 提供了 bgrewriteaof 命令。
    • 将内存中的数据以命令的形式保留到临时文件中,同时会 fork 出一条新过程来将文件重写。
    • 将整个内存中的数据库内容用命令的形式重写了一个新的 aof 文件
  • AOF 配置信息

    • ############################## APPEND ONLY MODE ###############################
      # By default Redis asynchronously dumps the dataset on disk. This mode is
      # good enough in many applications, but an issue with the Redis process or
      # a power outage may result into a few minutes of writes lost (depending on
      # the configured save points).
      #
      # The Append Only File is an alternative persistence mode that provides
      # much better durability. For instance using the default data fsync policy
      # (see later in the config file) Redis can lose just one second of writes in a
      # dramatic event like a server power outage, or a single write if something
      # wrong with the Redis process itself happens, but the operating system is
      # still running correctly.
      #
      # AOF and RDB persistence can be enabled at the same time without problems.
      # If the AOF is enabled on startup Redis will load the AOF, that is the file
      # with the better durability guarantees.
      appendonly no
      # The name of the append only file (default: "appendonly.aof")
      appendfilename "appendonly.aof"
    • # Redis supports three different modes:
      # no: don't fsync, just let the OS flush the data when it wants. Faster.
      # always: fsync after every write to the append only log. Slow, Safest.
      # everysec: fsync only one time every second. Compromise.
      
      # appendfsync always
      appendfsync everysec
      # appendfsync no
    • # 重写的机会 - 条件
      # Automatic rewrite of the append only file.
      # Redis is able to automatically rewrite the log file implicitly calling
      # BGREWRITEAOF when the AOF log size grows by the specified percentage.
      #
      # This is how it works: Redis remembers the size of the AOF file after the
      # latest rewrite (if no rewrite has happened since the restart, the size of
      # the AOF at startup is used).
      #
      # This base size is compared to the current size. If the current size is
      # bigger than the specified percentage, the rewrite is triggered. Also
      # you need to specify a minimal size for the AOF file to be rewritten, this
      # is useful to avoid rewriting the AOF file even if the percentage increase
      # is reached but it is still pretty small.
      #
      # Specify a percentage of zero in order to disable the automatic AOF
      # rewrite feature.
      
      auto-aof-rewrite-percentage 100
      auto-aof-rewrite-min-size 64mb
  • AOF 的触发策略

    • 每批改同步 always

      • 同步长久化 每次产生数据变更会被立刻记录到磁盘 性能较差但数据完整性比拟好
    • 每秒同步 everysec:

      • 异步操作,每秒记录 如果一秒内宕机,有数据失落
    • 不同 no:

      • 从不同步
  • AOF 的劣势和劣势

    • 劣势

      • AOF 能够更好的爱护数据不失落,个别 AOF 会每隔 1 秒,通过一个后盾线程执行一次 fsync 操作,最多失落 1 秒钟的数据。
      • AOF 日志文件没有任何磁盘寻址的开销,写入性能十分高,文件不容易破损。
      • AOF 日志文件即便过大的时候,呈现后盾重写操作,也不会影响客户端的读写。
      • AOF 日志文件的命令通过十分可读的形式进行记录,这个个性非常适合做灾难性的误删除的紧急复原。
    • 劣势

      • 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大
      • AOF 反对的写 QPS 会比 RDB 反对的写 QPS 低

        • QPS:Queries Per Second 意思是“每秒查问率”
        • TPS:是 TransactionsPerSecond 的缩写,也就是事务数 / 秒

RDB 和 AOF 的抉择

  • 成年人不做选择题

    • 如果同时应用 AOF 和 RDB,那么启动时以 AOF 为复原数据的模板
    • 抉择的话,两者加一起才更好。
    • 因为两个长久化机制你明确了,剩下的就是看本人的需要了,需要不同抉择的也不肯定,然而通常都是联合应用

主从复制集群

​ Redis 尽管读取写入的速度都特地快,然而也会产生读压力特地大的状况。为了分担读压力,Redis 反对主从复制,Redis 的主从构造能够采纳一主多从或者级联构造,Redis 主从复制能够依据是否是全量分为全量同步和增量同步。

搭建主从服务器

  • 在 Redis 主配置文件文件夹中创立配置文件
  • 主节点配置文件

    • ## 导入一个通用配置文件
      include /opt/lzj/redis/conf/redis.conf
      
      ## 以后主服务器端口
      port 7100
      ## 设置主服务明码
      requirepass 123456
      ## 以后主服务过程 ID
      pidfile /var/run/redis_7100.pid
      ## 以后主服务 RDB 文件名称
      dbfilename dump7100.rdb
      ## 以后主服务文件寄存门路
  • 从节点须要配置

    • 间接在配置文件中增加(永恒)
    • ## 导入一个通用配置文件
      include /opt/lzj/redis/conf/redis.conf
      
      ## 以后主服务器端口
      port 7200
      ## 以后主服务过程 ID
      pidfile /var/run/redis_7200.pid
      ## 以后主服务 RDB 文件名称
      dbfilename dump7200.rdb
      ## 以后主服务文件寄存门路
      dir /opt/lzj/redis/conf/ 
      
      ## 同步 master 节点的网络信息(低版本必须应用 slaveof, 高版本举荐应用 replicaof)replicaof 127.0.0.1 7100
      ## 设置 master 节点的明码信息
      masterauth 123456
      ## 从节点只做读的操作,保障主从数据的一致性
    
    - 在 redis 客户端命令行中输出(长期)- replicaof 127.0.0.1 7100
    - config set masterauth 123456
    
    - 完结从服务器的命运(完结)- slaveof no one

数据同步机制

Redis 的主从构造能够采纳一主多从或者级联构造,Redis 主从复制能够依据是否是全量分为全量同步和增量同步

主从刚刚连贯的时候,进行全量同步;全同步完结后,进行增量同步。

  • 全量同步

    • Redis 全量复制个别产生在 Slave 初始化阶段,这时 Slave 须要将 Master 上的所有数据都复制一份
    • 从服务器连贯主服务器,发送 SYNC 命令;
    • 主服务器接管到 SYNC 命名后,开始执行 BGSAVE 命令生成 RDB 文件并应用缓冲区记录尔后执行的所有写命令;
    • 主服务器 BGSAVE 执行完后,向所有从服务器发送快照文件,并在发送期间持续记录被执行的写命令;
    • 从服务器收到快照文件后抛弃所有旧数据,载入收到的快照;
    • 主服务器快照发送结束后开始向从服务器发送缓冲区中的写命令;
    • 从服务器实现对快照的载入,开始接管命令申请,并执行来自主服务器缓冲区的写命令;
  • 增量同步

    • Redis 增量复制是指 Slave 初始化后开始失常工作时主服务器产生的写操作同步到从服务器的过程。
    • 增量复制的过程次要是主服务器每执行一个写命令就会向从服务器发送雷同的写命令,从服务器接管并执行收到的写命令。
  • 主从复制的异步个性

    • 主从复制对于主 redis 服务器来说是非阻塞的

      • 这意味着当从服务器在进行主从复制同步过程中,主 redis 依然能够解决外界的拜访申请;
    • 主从复制对于从 redis 服务器来说也是非阻塞的

      • 这意味着,即便从 redis 在进行主从复制过程中也能够承受外界的查问申请,只不过这时候从 redis 返回的是以前老的数据

服务器断线重连

  • Redis 2.8 开始,如果遭逢连贯断开,从新连贯之后能够从中断处持续进行复制,而不用从新同步
  • 局部同步的实现依赖于在 master 服务器内存中给每个 slave 服务器保护了一份同步日志和同步标识
  • 每个 slave 服务器在跟 master 服务器进行同步时都会携带本人的同步标识和上次同步的最初地位
  • 当主从连贯断掉之后,slave 服务器隔断工夫(默认 1s)被动尝试和 master 服务器进行连贯
  • 如果从服务器携带的偏移量标识还在 master 服务器上的同步备份日志中
  • 那么就从 slave 发送的偏移量开始持续上次的同步操作
  • 如果 slave 发送的偏移量曾经不再 master 的同步备份日志中,则必须进行一次全量更新

Redis 的哨兵

Redis 的主从复制模式下,一旦主节点因为故障不能提供服务,须要手动将从节点降职为主节点,同时还要告诉客户端更新主节点地址

Sentinel 哨兵是 redis 官网提供的高可用计划,能够用它来监控多个 Redis 服务实例的运行状况

哨兵性能与作用

  • 监控(monitoring)

    • Sentinel 会一直地查看你的主服务器和从服务器是否运作失常。
  • 揭示(Notifation)

    • 当被监控的某个 Redis 服务器呈现问题时,Sentinel 能够通过 API 向管理员或者其余应用程序发送告诉。
  • 主动故障转移(Automatic failover)

    • 当一个主服务器不能失常工作时,Sentinel 会开始一次主动故障迁徙操作,它会将生效主服务器的其中一个从服务器降级为新的主服务器,并让生效主服务器的其余从服务器改为复制新的主服务器;当客户端试图连贯生效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群能够应用新主服务器代替生效服务器。

哨兵工作原理

  • 在 redis sentinel 中,一共有 3 个定时工作,通过这些工作,来发现新增节点和节点的状态。

    • 每 10 秒每个 sentinel 节点对 master 节点和 slave 节点执行 info 操作
    • 每 2 秒每个 sentinel 节点通过 master 节点的 channel(sentinel:hello)替换信息
    • 每 1 秒每个 sentintel 节点对 master 节点和 slave 节点以及其余的 sentinel 节点执行 ping 操作
  • 主观下线(SDOWN):以后 sentintel 节点认为某个 redis 节点不可用。

    • 如果一个实例(instance)间隔最初一次无效回复 PING 命令的工夫超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel 标记为主观下线。
    • 如果一个主服务器被标记为主观下线,那么正在监督这个主服务器的所有 Sentinel 节点,要以每秒一次的频率确认主服务器确实进入了主观下线状态。
  • 主观下线(ODOWN)肯定数量 sentinel 节点认为某个 redis 节点不可用。

    • 如果一个主服务器被标记为主观下线,并且有足够数量的 Sentinel(至多要达到配置文件指定的数量)在指定的工夫范畴内批准这一判断,那么这个主服务器被标记为主观下线。
    • 在个别状况下,每个 Sentinel 会以每 10 秒一次的频率,向它已知的所有主服务器和从服务器发送 INFO 命令。当一个主服务器被 Sentinel 标记为主观下线时,Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率,会从 10 秒一次改为每秒一次。
    • Sentinel 和其余 Sentinel 协商主节点的状态,如果主节点处于 SDOWN 状态,则投票主动选出新的主节点。将残余的从节点指向新的主节点进行数据复制。
  • 当没有足够数量的 Sentinel 批准主服务器下线时,主服务器的主观下线状态就会被移除。当主服务器从新向 Sentinel 的 PING 命令返回无效回复时,主服务器的主观下线状态就会被移除。

故障转移流程

  • 哨兵外部领导者选举

    • 1). 每个做主观下线的 sentinel 节点向其余 sentinel 节点发送下面那条命令,要求将它设置为领导者。

      2). 收到命令的 sentinel 节点如果还没有批准过其余的 sentinel 发送的命令(还未投过票),那么就会批准,否则回绝。

      3). 如果该 sentinel 节点发现自己的票数曾经过半且达到了 quorum 的值,就会成为领导者。

      4). 如果这个过程呈现多个 sentinel 成为领导者,则会期待一段时间从新选举。

  • Master 选举

    • 抉择 slave-priority 最高的 slave 节点
    • 抉择复制偏移量最大的节点
    • 选 runId 最小的(启动最早)
  • 状态更换

    • 选举出新的 master 节点,其余的节点变更为新的 master 节点的 slave 节点
    • 原有的 master 节点从新上线,成为新的 master 节点的 slave 节点
  • 告诉客户端

    • 当所有节点配置完结后,sentinel 会告诉客户端节点变更信息。
    • 客户端连贯新的 master 节点

哨兵环境搭建

  • 搭建多台计算机的主从集群

    • Host 端口 节点分类 Sentinel
      192.168.58.161 20601 master 20600
      192.168.58.162 20601 slave 20600
      192.168.58.163 20601 slave 20600
    • Master 节点

      • ## 导入一个通用配置文件
        include /opt/lzj/redis/conf/redis.conf
        
        ## 以后主服务器 IP 和端口
        bind 0.0.0.0
        port 20601
        ## 去掉平安模式
        protected-mode no
        ## 设置主服务明码
        requirepass 123456
        ## 以后主服务过程 ID
        pidfile /var/run/redis_20601.pid
        ## 以后主服务 RDB 文件名称
        dbfilename dump20601.rdb
        ## 以后主服务文件寄存门路
        dir /opt/lzj/redis/conf/ 
        ## 设置 master 节点的明码信息
        masterauth 123456
        ## 设置时候后盾启动
    • Slave 节点

      • ## 导入一个通用配置文件
        include /opt/lzj/redis/conf/redis.conf
        
        ## 以后主服务器 IP 和端口
        bind 0.0.0.0
        port 20601
        ## 去掉平安模式
        protected-mode no
        ## 设置主服务明码
        requirepass 123456
        ## 以后主服务过程 ID
        pidfile /var/run/redis_20601.pid
        ## 以后主服务 RDB 文件名称
        dbfilename dump20601.rdb
        ## 以后主服务文件寄存门路
        dir /opt/lzj/redis/conf/ 
        
        ## 同步 master 节点的网络信息(低版本必须应用 slaveof, 高版本举荐应用 replicaof)replicaof 192.168.201.101 20601
        ## 设置 master 节点的明码信息
        masterauth 123456
        ## 从节点只做读的操作,保障主从数据的一致性
        slave-read-only yes 
        ## 设置时候后盾启动
      
      - 三台计算机别离启动 Redis
      
      - redis-server /opt/lzj/redis/conf/redis20601.conf
  • 一个持重的 RedisSentinel 集群,应该应用至多三个 Sentinel 实例,并且保障将这些实例放到不同的机器上,甚至不同的物理区域

    ## redis-sentinel /opt/lzj/redis/conf/sentinel.conf
    
    ## 设置哨兵的接口
    port 20600
    
    ## sentinel monitor 关键字
    ## master20601 给主从服务器集群起一个名字(监控主服务器,从服务器的信息也就获取了)
    ## 192.168.58.161 20601 主服务器的 IP 和端口
    ## 2 主服务器生效的统计数,超过 2 票就认为生效
    sentinel monitor master20601 192.168.201.101 20601 2
    
    ## 设置主服务器明码
    sentinel auth-pass master20601 123456
    
    ## 主服务器下线超过 10 秒就进行切换(默认 30S)sentinel down-after-milliseconds master20601 10000
    
    ## 故障转移超时工夫 
    sentinel failover-timeout master20601 180000
    
    ## 故障转移时,容许有多少个 slave 同时对新的 master 进行同步, 这个数字越小,实现 failover 所需的工夫就越长
    sentinel parallel-syncs master20601 1
    
    ## 敞开平安校验
    protected-mode no

Redis 的高可用

在 Redis 中,实现高可用的技术次要包含长久化、复制、哨兵和集群,上面简略阐明它们的作用,以及解决了什么样的问题:

  • 长久化:长久化是最简略的高可用办法。它的次要作用是数据备份,行将数据存储在硬盘,保证数据不会因过程退出而失落。
  • 复制:复制是高可用 Redis 的根底,哨兵和集群都是在复制根底上实现高可用的。

    • 复制次要实现了数据的多机备份以及对于读操作的负载平衡和简略的故障复原。
    • 缺点是故障复原无奈自动化、写操作无奈负载平衡、存储能力受到单机的限度。
  • 哨兵:在复制的根底上,哨兵实现了自动化的故障复原。缺点是写操作无奈负载平衡,存储能力受到单机的限度。
  • 集群:通过集群,Redis 解决了写操作无奈负载平衡以及存储能力受到单机限度的问题,实现了较为欠缺的高可用计划。

集群设计思维

  • cluster 能够说是 sentinel 和主从模式的结合体,通过 cluster 能够实现主从和 master 重选性能
  • 不同节点别离治理不同的 key
  • 同一个 Key 的操作只让一个 master 去解决
  • 为了保障 master 节点的(单点故障和效率)问题,每个主节点至多筹备一个 slave 节点
  • 集群是一个能够在多个 Redis 节点之间进行数据共享的设施
  • 集群不反对那些须要同时解决多个键的 Redis 命令

一致性 Hash

业务场景

  • 一个电商平台,须要应用 Redis 存储商品的图片资源,存储的格局为键值对,key 值为图片名称,Value 为该图片所在的文件服务器的门路,咱们须要依据文件名,查找到文件所在的文件服务器上的门路,咱们的图片数量大略在 3000w 左右,依照咱们的规定进行分库,规定就是随机调配的,咱们以每台服务器存 500w 的数量,部署 12 台缓存服务器,并且进行主从复制

  • 应用 Hash 的形式,每一张图片在进行分库的时候都能够定位到特定的服务器

  • 问题:

    • Redis 服务器变动时,所有缓存的地位都会产生扭转

      • Redis 缓存服务器 6 台减少到了 8 台
      • Redis 缓存服务器 6 台的服务器集群中呈现故障时缩小到 5 台

算法原理

  • 取模

    • 一致性的 Hash 算法是对 2 的 32 方 取模
    • 整个空间按顺时针方向组织,圆环的正上方的点代表 0,0 点右侧的第一个点代表 1,以此类推,2、3、4、5、6……直到 2^32-1
    • 这个由 2^32 个点组成的圆环称为 Hash 环
  • 服务器

    • 将各个服务器应用 Hash 进行一个哈希,这样每台机器就能确定其在哈希环上的地位
  • 数据

    • 数据 key 应用雷同的函数 Hash 计算出哈希值,并确定此数据在环上的地位
  • 定位

    • 沿环顺时针“行走”,第一台遇到的服务器就是数据应该定位到的服务器

算法容错性

  • 当咱们增加服务器或者删除服务器
  • 它只影响解决节点的下一个节点

数据歪斜与虚构节点

  • 平均一致性 hash 的指标是如果服务器有 N 台,客户端的 hash 值有 M 个,
  • 那么每个服务器应该解决大略 M / N 个用户的。也就是每台服务器负载尽量平衡

Redis 的 Slot 槽

  • Redis 集群应用数据分片(sharding)而非一致性哈希(consistencyhashing)来实现:
  • 一个 Redis 集群蕴含 16384 个哈希槽(hashslot),数据库中的每个键都属于这 16384 个哈希槽的其中一个,集群应用公式 CRC16(key)%16384 来计算键 key 于哪个槽,其中 CRC16(key)语句用于计算键 key 的 CRC16 校验和
  • 将一个哈希槽从一个节点挪动到另一个节点不会造成节点阻塞,所以无论是增加新节点还是移除已存在节点,又或者扭转某个节点蕴含的哈希槽数量,都不会造成集群下线。
  • 对象保留到 Redis 之前先通过 CRC16 哈希到一个指定的 Node
  • 每个 Node 被平均分配了一个 Slot 段,对应着 0-16383Slot 不能反复也不能缺失,否则会导致对象反复存储或无奈存储。
  • Node之间也相互监听,一旦有 Node 退出或者退出,会依照 Slot 为单位做数据的迁徙

    • Node1如果掉线了,0-5640这些 Slot 将会均匀摊派到 Node2Node3
  • 优缺点

    • 长处:

      • Redis 的写操作摊派到了多个节点上,进步写的并发能力,扩容简略。
    • 毛病:

      • 每个 Node 承当着相互监听、高并发数据写入、高并发数据读出,工作工作沉重

搭建集群环境

节点散布

  • Host Master Slave
    192.168.58.161 30601 30602
    192.168.58.162 30601 30602
    192.168.58.163 30601 30602

配置文件

  • ## 导入默认配置文件
    include /opt/lzj/redis/conf/redis.conf
    
    ## 以后主服务器 Host 和端口
    bind 0.0.0.0
    port 30601
    ## 后盾模式运行
    daemonize no
    ## 敞开保护模式
    protected-mode no
    ## 设置主服务明码
    requirepass 123456
    ## 设置从服务器明码
    masterauth 123456
    ## 以后主服务过程 ID
    pidfile /var/run/redis_30601.pid
    ## 以后主服务 RDB 文件名称
    dbfilename dump30601.rdb
    ## 以后主服务文件寄存门路
    dir /opt/lzj/redis/conf/
    ## 开启 aof 长久化形式
    appendonly yes   
    ## 设置 AOF 文件名字
    appendfilename "appendonly30601.aof"
    
    ## 集群相干
    cluster-enabled yes
    cluster-config-file nodes-30601.conf
    cluster-node-timeout 5000
  • 别离启动 6 个节点

    • redis-server /opt/lzj/redis/conf/redis20601.conf

构建集群

  • # --cluster-replicas 1  示意主从配置比,1 示意的是 1:1,前三个是主,后三个是从
    # 若配置文件中设置的明码,则还须要加上 -a passwod
    redis-cli --cluster create 192.168.201.101:30601 192.168.201.102:30601 192.168.201.103:30601 192.168.201.101:30602 192.168.201.102:30602 192.168.201.103:30602 --cluster-replicas 1 -a 123456
  • 查看集群信息

    • redis-cli -h 127.0.0.1 -p 20601 -a 123456
      # 查看集群信息
      cluster info    
      # 查看节点列表
    
    ![image-20200718171927687](https://i0.hdslb.com/bfs/album/8cf3f1aa3c988e550f6d935dbb84239d8507f20c.png)
    
    ![image-20200718172140358](https://i0.hdslb.com/bfs/album/f967b0b933ac661a006c7d68cc4ea9557c7e4cc2.png)

拜访集群

  • redis-cli -h bd1602 -p 30602 -a 123456
  • redis-cli -c -h bd1602 -p 30602 -a 123456

Redis 的常见场景

用户回复频率管制

  • 我的项目的社区性能里,不可避免的总是会遇到垃圾内容,一沉睡来你会发现首页忽然会被某些歹意的帖子和广告刷屏了,如果不采取适当的机制来管制就会导致用户体验受到重大的影响
  • 管制广告垃圾贴的策略很多,高级一点的能够通过 AI,最简略的形式是通过关键词扫描,还有比拟罕用的一种形式是频率管制,限度单个用户内容的生产速度,不通等级的用户会有不同的频率控制参数
  • 应用 Redis 来实现频率管制(青铜 1 小时 3 贴 白银 1 小时 5 贴 黄金 1 小时 8 贴)

斗鱼日榜

24 小时热销榜

  • 如果小说榜单只有 10 个地位,那么对于第 11 名小说太不偏心
  • 那么如果借助于 10 个地位显示前 20 名的小说???

统计每日沉闷用户

  • Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的长处是,在输出元素的数量或者体积十分十分大时,计算基数所需的空间总是固定 的、并且是很小的。
  • 在 Redis 外面,每个 HyperLogLog 键只须要破费 12 KB 内存,就能够计算靠近 2^64 个不同元素的基 数。这和计算基数时,元素越多消耗内存就越多的汇合造成鲜明对比。

摇一摇疾速获取间隔

  • GEO性能在 Redis3.2 版本提供,反对存储地理位置信息用来实现诸如左近地位、摇一摇这类依赖于地理位置信息的性能.geo 的数据类型为 zset.
  • https://blog.csdn.net/qq_3420…

感激大家的认同与反对,小编会继续转发《乐字节》优质文章

正文完
 0