栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

redis笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

redis笔记

文章目录
  • redis学习计划
  • 一、Redis介绍、优缺点和使用场景
  • 二、linux环境下安装和参数说明
    • 2.1安装
    • 2.2参数说明
  • 三、各数据类型及其使用场景
    • String(字符串)
    • Hash(哈希)
    • List(列表)
    • Set(集合)
    • zset(Sorted Set:有序集合)
  • 四、redis持久化、数据恢复和备份
    • RDB
    • AOF
  • 五、redis集群
    • redis主从配置
    • redis哨兵机制
    • redis Clsuter集群解决方案
      • 1、启动启命令
      • 2、节点握手(meet)
      • 3、指派槽
      • 4、主从关系配置
  • 六、如何保证DB和缓存一致性?
  • 七、Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案
  • 八、redis问答


redis学习计划

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Redis介绍、优缺点和使用场景

redis是开源免费的,基于键值的存储服务系统,支持多种数据类型,性能高,功能丰富

特性:
速度快:性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
持久化:支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
多种数据结构:不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
功能丰富:支持 publish/subscribe, 通知, key 过期等等特性。
原子性:所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
主从复制:服务器的数据可以同步到从服务器上,为高可用提供可能

二、linux环境下安装和参数说明 2.1安装
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
tar -zxvf redis-5.0.7.tar.gz
mv redis-5.0.7 /usr/local/redis 不需要先创建/usr/local/redis文件夹
cd /usr/local/redis
make
make install

!!如果有报错/bin/sh: cc: command not found?
	* 请检查是否安装了 gcc gcc-c++ libstdc++-devel,
!!再执行报错“zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory”?
	* 使用 make MALLOC=libc && make install 执行 

mkdir ./bin
mv ./src/redis-server  ./src/redis-cli ./src/redis-sentinel  ./bin/

vi redis.conf
* bind 0.0.0.0 开发环境访问
* daemonize yes 设置后台运行
* port 6379
* pidfile /var/run/redis_6379.pid
* dbfilename dump_6379.rdb
* requirepass password 修改密码

> redis-server ./redis.conf 启动
redis-cli 进入命令行,进行简单的命令操作

> shutdown save 关闭redis,同时持久化当前数据
redis-server ./redis.conf 再次启动redis

将redis配置成系统服务,redis/utils中自带命令,我们只需修改参数
/usr/local/redis/utils/./install_server.sh
[root~ utils]# ./install_server.sh
Welcome to the redis service installer
Please select the redis port for this instance: [6379] 默认端口不管
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] /usr/local/redis/redis.conf 修改配置文件路径
Please select the redis log file name [/var/log/redis_6379.log] /usr/local/redis/redis.log 修改日志文件路径
Please select the data directory for this instance [/var/lib/redis/6379] /usr/local/redis/data 修改数据存储路径
Please select the redis executable path [/usr/local/bin/redis-server]
Selected config:
Port           : 6379
Config file    : /usr/local/redis/redis.conf
Log file       : /usr/local/redis/redis.log
Data dir       : /usr/local/redis/data
Executable     : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
chkconfig --list | grep redis 查看redis服务配置项
redis_6379      0:off   1:off   2:on    3:on    4:on    5:on    6:off
服务名是redis_6379
2.2参数说明

通过CONFIG命令查看配置

config get *

  1) "dbfilename"
  2) "dump.rdb"
  3) "requirepass"
  4) ""
  5) "masterauth"
  6) ""
  7) "unixsocket"
  8) ""
  9) "logfile"
 10) ""
 11) "pidfile"
 12) "/var/run/redis.pid"
 13) "maxmemory"
 14) "0"
 15) "maxmemory-samples"
 16) "3"
 17) "timeout"
 18) "0"
 19) "tcp-keepalive"
 20) "0"
 21) "auto-aof-rewrite-percentage"
 22) "100"
 23) "auto-aof-rewrite-min-size"
 24) "67108864"
 25) "hash-max-ziplist-entries"
 26) "512"
 27) "hash-max-ziplist-value"
 28) "64"
 29) "list-max-ziplist-entries"
 30) "512"
 31) "list-max-ziplist-value"
 32) "64"
 33) "set-max-intset-entries"
 34) "512"
 35) "zset-max-ziplist-entries"
 36) "128"
 37) "zset-max-ziplist-value"
 38) "64"
 39) "hll-sparse-max-bytes"
 40) "3000"
 41) "lua-time-limit"
 42) "5000"
 43) "slowlog-log-slower-than"
 44) "10000"
 45) "latency-monitor-threshold"
 46) "0"
 47) "slowlog-max-len"
 48) "128"
 49) "port"
 50) "6379"
 51) "tcp-backlog"
 52) "511"
 53) "databases"
 54) "16"
 55) "repl-ping-slave-period"
 56) "10"
 57) "repl-timeout"
 58) "60"
 59) "repl-backlog-size"
 60) "1048576"
 61) "repl-backlog-ttl"
 62) "3600"
 63) "maxclients"
 64) "4064"
 65) "watchdog-period"
 66) "0"
 67) "slave-priority"
 68) "100"
 69) "min-slaves-to-write"
 70) "0"
 71) "min-slaves-max-lag"
 72) "10"
 73) "hz"
 74) "10"
 75) "no-appendfsync-on-rewrite"
 76) "no"
 77) "slave-serve-stale-data"
 78) "yes"
 79) "slave-read-only"
 80) "yes"
 81) "stop-writes-on-bgsave-error"
 82) "yes"
 83) "daemonize"
 84) "no"
 85) "rdbcompression"
 86) "yes"
 87) "rdbchecksum"
 88) "yes"
 89) "activerehashing"
 90) "yes"
 91) "repl-disable-tcp-nodelay"
 92) "no"
 93) "aof-rewrite-incremental-fsync"
 94) "yes"
 95) "appendonly"
 96) "no"
 97) "dir"
 98) "/home/deepak/Downloads/redis-2.8.13/src"
 99) "maxmemory-policy"
100) "volatile-lru"
101) "appendfsync"
102) "everysec"
103) "save"
104) "3600 1 300 100 60 10000"
105) "loglevel"
106) "notice"
107) "client-output-buffer-limit"
108) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
109) "unixsocketperm"
110) "0"
111) "slaveof"
112) ""
113) "notify-keyspace-events"
114) ""
115) "bind"
116) ""

参数说明

redis.conf 配置项说明如下:

  1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程

    daemonize no

  2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定

    pidfile /var/run/redis.pid

  3. 指定Redis监听端口,默认端口为6379

    port 6379

  4. 绑定的主机地址,监听在主机的哪个ip上

    bind 127.0.0.1

  5. 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能

    timeout 300

  6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose

    loglevel verbose

  7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null

    logfile stdout

  8. 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id

    databases 16

  9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

    save

    Redis默认配置文件中提供了三个条件:

    save 900 1

    save 300 10

    save 60 10000

    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

  10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大

    rdbcompression yes

  11. 指定本地数据库文件名,默认值为dump.rdb

    dbfilename dump.rdb

  12. 指定本地数据库存放目录

    dir ./

  13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步

    slaveof

  14. 当master服务设置了密码保护时,slave服务连接master的密码

    masterauth

  15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭

    requirepass foobared

  16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

    maxclients 10000

  17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区

    maxmemory

  18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no

    appendonly no

  19. 指定更新日志文件名,默认为appendonly.aof

    appendfilename appendonly.aof

  20. 指定更新日志条件,共有3个可选值: no:表示等操作系统进行数据缓存同步到磁盘(快) always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全) everysec:表示每秒同步一次(折衷,默认值)

    appendfsync everysec

  21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)

    vm-enabled no

  22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享

    vm-swap-file /tmp/redis.swap

  23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0

    vm-max-memory 0

  24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值

    vm-page-size 32

  25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。

    vm-pages 134217728

  26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4

    vm-max-threads 4

  27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启

    glueoutputbuf yes

  28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法

    hash-max-zipmap-entries 64

    hash-max-zipmap-value 512

  29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)

    activerehashing yes

  30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

    include /path/to/local.conf

三、各数据类型及其使用场景

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)
  • string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。
  • string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
  • string类型是Redis最基本的数据类型,一个键最大能存储512MB

实例:

redis 127.0.0.1:6379> SET name "redis.net.cn"
OK
redis 127.0.0.1:6379> GET name
"redis.net.cn"

使用场景:

缓存/计数器/分布式锁/Web集群session共享/分布式系统全局序号

Hash(哈希)
  • 是一个键值对集合。
  • 是一个string类型的field和value的映射表,hash特别适合用于存储对象。

实例:

redis 127.0.0.1:6379> HMSET user:1 username u1 password p1 points 200
OK
redis 127.0.0.1:6379> HGETALL user:1
1) "username"
2) "u1"
3) "password"
4) "p1"
5) "points"
6) "200"
List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。
实例:

redis 127.0.0.1:6379> lpush l1 redis
(integer) 1
redis 127.0.0.1:6379> lpush l1 mongodb
(integer) 2
redis 127.0.0.1:6379> lpush l1 rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange l1 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
Set(集合)
  • Redis的Set是string类型的无序集合。
  • 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

sadd 命令
添加一个string元素到,key对应的set集合中,成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误。

sadd key member

实例:

redis 127.0.0.1:6379> sadd s1 redis
(integer) 1
redis 127.0.0.1:6379> sadd s1 mongodb
(integer) 1
redis 127.0.0.1:6379> sadd s1 rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd s1 rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers s1
 
1) "rabitmq"
2) "mongodb"
3) "redis"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

zset(Sorted Set:有序集合)
  • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
  • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
  • zset的成员是唯一的,但分数(score)却可以重复。

zadd 命令
添加元素到集合,元素在集合中存在则更新对应score

zadd key score member 

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

实例:

127.0.0.1:6379> ZADD s1 1 S1
(integer) 1
127.0.0.1:6379> ZADD s1 2 S2
(integer) 1
127.0.0.1:6379> ZADD s1 3 S3
(integer) 1
127.0.0.1:6379> ZADD s1 4 A1
(integer) 1
127.0.0.1:6379> ZADD s1 4 A2
(integer) 1
127.0.0.1:6379> ZADD s1 4 A3
(integer) 1

127.0.0.1:6379> ZRANGE s1 0 10 WITHSCORES
 1) "S1"
 2) "1"
 3) "S2"
 4) "2"
 5) "S3"
 6) "3"
 7) "A1"
 8) "4"
 9) "A2"
10) "4"
11) "A3"
12) "4"

通过索引区间返回有序集合指定区间内的成员

ZRANGE key start stop [WITHSCORES]

通过分数返回有序集合指定区间内的成员
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]

四、redis持久化、数据恢复和备份

持久化:将所有保存在内存中的数据,异步的写到磁盘中,redis有快照(redis RDB)和写日志(redis AOF)两种方式。

RDB
RDB文件(二进制文件)到硬盘中,启动后载入RDB文件到内存,如果存在老的rdb文件,新的会替换老的,新的会先写到一个临时文件中。

三种触发机制:

  • save(同步):用于创建当前数据库的备份,会产生阻塞。
  • bgsave(异步):创建备份但不会阻塞,客户端执行bgsave之后,redis会使用linux的一个fork()命令生成主进程的一个子进程(fork的操作会执行一个内存页的拷贝,使用copy-on-write策略),子进程会创建RDB文件,创建完毕后将成功的消息返回给redis。fork()出来的子进程执行快的话不会阻塞主进程,否则也会阻塞redis,阻塞的实际点就是生成出来这个子进程。由于是异步,在创建的过程中还有其他命令在执行,如何保证RDB文件是最新的呢?在数据量大的时候bgsave才能突出优点。
  • 自动触发(异步):根据配置文件中save s num,多少秒内有多少次changes,会异步(bgsave)生成一个RDB文件。

配置:

dbfilename dump.rdb    // RDB文件名,起多个redis服务时不要重复
dir ./    			   // RDB文件存放目录
stop-writes-on-bgsave-error yes  // 当bgsave发生错误是停止写RDB文件
rdbcompression yes     // 采用压缩格式
rdbchecksum yes        // 采用校验和
AOF

RDB带来的问题:耗时、耗费性能(fork、IO)、不可控(突然宕机的情况)
AOF则是将redis的修改操作命令会刷新到缓冲区,然后根据aof配置的策略,异步追加到AOF文件中,宕机后可以通过AOF恢复,数据基本完整。

AOF策略:

  • always:来一条命令写一条,不丢失数据,IO开销较大.
  • everysec:每秒把缓冲区fsync到AOF文件,只丢失1秒钟的数据.
  • no:系统决定什么时候将缓冲区写到AOF文件中,不可控.

AOF配置:

appendonly yes
appendfilename “”
appendfsync everysec
dir /xx
no-appendfsync-on-rewrite yes AOF在重启之后恢复,要权衡是否开启AOF日志追加的功能,这个时候IO很大,如果设置为yes,也就意味着在恢复之前的日志数据会丢失

AOF重写:
因为aof持久化是通过记录写的命令来保存数据和状态的,所以随着时间增加文件体积会越来越大,为了解决这个问题redis提供了aof重写机制,aof重写是优化一些命令使其整合为一条,过滤重复和过期的命令,以此减少磁盘的占用量。
AOF重写其实是一个有歧义的名字,实际上重写工作是针对数据库的当前状态来进行的,重写过程中不会读写、也不适用原来的AOF文件;

AOF重写——触发条件:

  • 没有BGSAVE命令(RDB持久化)/ AOF持久化在执行;
  • 没有BGREWRITEAOF在进行;
  • 当前AOF文件大小要大于server.aof_rewrite_min_size(默认为1MB),或者在redis.conf配置了auto-aof-rewrite-min-size大小;
  • 当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比(在配置文件设置了auto-aof-rewrite-percentage参数,不设置默认为100%)
  • 如果前面三个条件都满足,并且当前AOF文件大小比最后一次AOF重写时的大小要大于指定的百分比,那么触发自动AOF重写。

AOF重写——触发方式:

  • 手动触发:直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。

  • 自动触发:通过设置auto-aof-rewrite-min-size选项(AOF文件到达多大的时候才开始重写)和auto- aof-rewrite- percentage选项(AOF文件的增长率到达了多大才开始重写)来自动执行BGREWRITEAOF。

  • 只有当auto-aof- rewrite- -min-size和auto-aof -rewrite-percentage两个选项同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。

注意:AOF文件的增长率:(aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage

五、redis集群

redis集群实现了对redis的水平扩展,将整个数据库分布存储在各个节点,提高并发量,扩展数据量。

redis主从配置

使用slaeof命令,在从redis中执行slave masterip:port使其成为master的从服务器,就能从master拉取数据了;执行slaveof no one清除掉不成为从节点,但是数据不会清除;

配置:

 slaveof {master-ip} {port}
 slave-read-only yes
 masterauth {master-passwd}

修改配置, slaveof ip port / slave-read-only yes(从节点只做都操作);配置要更改的话,要重启,所以选择的时候谨慎

弊端:

  • master/slave宕机时,主从模式没有实现完全的自动故障转移
  • 读写分离时,流量分摊到从节点,可能遇到复制数据延迟,也可能读到过期的数据
  • 主从内存配置不一致,可能会导致丢失数据
  • 单机主节点复制风暴,当一主多从,master重启之后,所有从节点都会进行全量复制,很容易造成redis服务不可用
redis哨兵机制

Redis Sentinel是一个监控redis主从以及实施故障转移的工具,sentinel不是一个是多个的(会选举出一个master sentinel),这样可以保证sentinel的高可用和公平(不是一个sentinel判断不可用就不可用),可以把Redis Sentinel看成一个redis的额外进程,用来监控reids服务的可用与不可用;客户端不再记住redis的地址,而是记录sentinel的地址,sentinel知道谁是真的master;当多个sentinel发现并确认master有问题,sentinel内部会先选出来一个领导,让这个领导来完成故障的转移(因为执行slave no noe/new master这些命令只需要一个sentinel就够了),sentinel从slave中选举一个作为master,然后通知其他的slave去新的master获取数据。sentinel可以监控多套master-slave。

安装配置:
配置开启sentinel监控主节点(sentinel是特殊的redis):sentinel默认端口是23679

sentinel monitor mymaster 127.0.0.1 7000 2 监控的主节点名字是mymaster,2表示2个sentinel觉得当前master有问题提才发生故障转移
sentinel down-after-milliseconds mymaster 30000 表示30秒不通之后就停掉master
sentinel parallel-syncs mymaster 1 表示每次并发的复制是1个在复制,这样可以减少master的压力
sentinel failover-timeout mymaster 180000 故障转移时间

主观下线和客观下线:
主观下线(SDOWN): 如果监控的服务器节点在 down-after-milliseconds设置的毫秒时效内没有响应检测,则会被判定为主观下线;这个状态适用所有服务器节点。

客观下线(ODOWN):主服务器节点在发生故障的时候,sentinel 会通过 is-master-down-by-addr 命令向其他 sentinel 节点询问 该主服务器节点的状态,如果超过 quorum 个数的哨兵节点都认为 主服务器节点不可达,则判定为客观下线;这个状态只会针对 主服务器节点

领导者选举:
每个做完主观下线的sentinel节点,都会向其他sentinel节点发送is-master-down-by-addr命令,要求将自己设置为领导者,那么收到该命令的sentinel如果在之前未收到其他sentinel的命令的话,就会同意这个请求,否则拒绝。每个sentinel只有一个同意票,这个同意票给第一个问自己的节点,票发完后,如果这个sentinel节点发现自己拥有的票数超过sentinel集合半数并且操作quorum,那么它将成为领导者;如果此过程有多个sentinel节点成为领导者,那么过段时间将重新进行一次选举。领导者选举使用的是一个Raft算法,以上是抽象过程。所以sentinel的个数(>=3最好为奇数)和quorum的个数需要合理配置。

故障转移(sentinel领导者节点完成):
从slave节点中选出合适的节点作为master节点,该节点会执行salveof no one 命令成为master节点,并向其他slave节点发送命令,让其成为新master节点的slave,向slave节点发送RDB和buffer进行同步。

redis Clsuter集群解决方案

当业务并发量和数据量远超单台能力上限时,可以考虑分布式的解决方案,使用多台服务器,把数据分到不同的位置,分摊集中的压力

Redis 集群的优势:

  • 自动分割数据到不同的节点
  • 整个集群的部分节点失败的情况下,能够继续处理命令

Redis 集群的数据分片:
redis集群引入了hash槽的概念,Redis集群共有16384个hash槽,每个key通过CRC16校验后对16384取模来决定放置到哪个槽,集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点

  • 节点A包含0到5500号hash槽
  • 节点B包含5501到11000号hash槽
  • 节点C包含11001到16384号hash槽

从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

安装配置:
至少准备6个节点,3主3从

port ${port}
daemonize yes
dir "/path"
dbfilename "dump-${port}.rdb"
logfile "${port}.log"
cluster-enabled yes
cluster-config-file nodes-${port}.conf #redis启动后这个nodes-port.conf会自动生成
cluster-node-timeout 5000

Redis 5开始可以使用redis-cli --cluster来创建集群,命令语法和redis-trib.rb脚本一样,省去了配置ruby环境的步骤,以下以redis-cli --cluster方式创建

1、启动启命令

redis-server redis-7000.conf / redis-server redis-7001.conf /…, 此时开启的节点都是相互孤立的没有任何通信, 查看当前状态

127.0.0.1:7000> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:0
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
2、节点握手(meet)
redis-cli -h 127.0.0.1 -p 7000 cluster meet 127.0.0.1 7001
[root@xx cluster]# redis-cli -p 7000 cluster meet 47.x.x.16 7001
OK
[root@xx cluster]# redis-cli -p 7000 cluster nodes
862e370d2342cf6bf883421003846e171770234e :7000@17000 myself,master - 0 0 0 connected
886b6e6c29f985f7f85acb1bf548d0937918eca3 4.x.x.6:7001@17001 handshake - 0 0 0 connected

redis-cli -h 127.0.0.1 -p 7000 cluster meet 127.0.0.1 7002
redis-cli -h 127.0.0.1 -p 7000 cluster meet 127.0.0.1 7003
redis-cli -h 127.0.0.1 -p 7000 cluster meet 127.0.0.1 7004
redis-cli -h 127.0.0.1 -p 7000 cluster meet 127.0.0.1 7005
3、指派槽
redis-cli -h 127.0.0.1 -p 7000 cluster addslots {0...5461}
redis-cli -h 127.0.0.1 -p 7001 cluster addslots {5462...10922}
redis-cli -h 127.0.0.1 -p 7002 cluster addslots {10923...16383}
4、主从关系配置
redis-cli -h 127.0.0.1 -p 7003 cluster replicate ${node-id-7000}
redis-cli -h 127.0.0.1 -p 7004 cluster replicate ${node-id-7001}
redis-cli -h 127.0.0.1 -p 7005 cluster replicate ${node-id-7002}

常用命令:
cluster notes 查看集群的node几点情况
cluster slots 查看slots的分布
cluster info 查看当前集群的状态,这个命令可以看到集群是否属于可用状态
redis-cli -c -p x 注意加-c,表示集群

集群通信:
16379 端口号是用来进行节点间通信的,也就是 cluster bus 的东西,cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一种二进制的协议,gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

六、如何保证DB和缓存一致性?

对于热点数据的读操作是从redis读取的,但是写的时候是需要在数据库和缓存中进行,涉及到双写就必然会存在双写不一致的问题。所以只能通过一些解决方案尽可能的保证双写一致。

可尝试在读的时候先从Redis读取,如果Redis中没有,那么再去数据库中读,读完之后放回Redis,然后返回响应。写的时候先删除缓存,然后再去写入数据库,然后等待100毫秒再次删除缓存

七、Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案

缓存击穿,是指存在热点数据,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

缓存击穿 解决方案:

  • 将热点数据设为永不过期
  • 加互斥锁,当缓存中没数据时,第一个进入的线程获取锁,并去数据库取数据,在没释放锁之前,其他线程会等待,并重新取去缓存取数据

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。

缓存穿透 解决方案:

  • 接口层增加校验
  • 从缓存和数据库都没找到,可以将对应key-value设置为一个临时的key-null,防止不停的对一个数据进行暴力攻击
  • 引入布隆过滤器,事先把存在的key都放到redis的Bloom Filter 中,他的用途就是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。
    剖析:布隆过滤器可能会误判,放过部分请求,当不影响整体,所以目前该方案是处理此类问题最佳方案。

缓存雪崩,是指在某一个时间段,缓存集中过期失效。

缓存雪崩 解决方案:

  • 随机设置过期时间,避免同一时间大量数据过期现象发生
  • 热点数据设置永不过期
  • redis设置持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据
八、redis问答

布隆过滤器(bloomfilter,以下简称bf)是用误差率来换取空间,并且是极大的提升了空间利用率。我们可以利用bf技术,只用极小的空间(相比于set)就能够处理这种大基数的元素查询,虽然不能保证全部正确,但是用少量的误差,配合DB,可以使服务器的负载控制在可以接受的范围。


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/874420.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号