JAVA-第十一部分-Redis

224 阅读21分钟

NoSQL

  • Not-Only SQL,泛指非关系型的数据库,作为关系型数据库的补充
  • 解决海量用户和高并发的问题

解决方案

  • 商品基本信息 Mysql
  • 商品附加信息 MongoDB
  • 商品图片信息 分布式文件系统
  • 搜索关键字 ES、Lucene、solr
  • 热点信息(高频、波段性) redis、memcache、tair image.png

Redis

  • mac安装 brew install redis
  • 可视化工具 Another Redis Desktop Manager
  • 提供基础数据,减少业务与数据的耦合度
  • Remote Dictionary Server,键值对数据库
  • 单线程机制,数据间没有必然的关联
  • 数据类型 string、list、hash、set、sorted_set(有序集合)
  • 持久化,数据灾难恢复
  • 数值最大范围 +-的long最大值
  • key命名
表名:主键:主键值:属性名,如user:id:3123:fans
//json格式
表名:主键:主键值 -> {属性一:值,属性二:值,属性三:值...}

应用

  • 热点数据查询
  • 任务队列,秒杀、抢购、购票
  • 即时信息、时效信息控制
  • 分布式数据

启动

  • 客户端 redis-cli 退出quit 关闭服务端SHUTDOWN
  • 服务端 redis-server

基本操作

  • 清屏 clear
  • 帮助信息 help
  • 获取当前时间 time

数据类型

  • key永远是String

string

  • 存储单个数据
  • 整体性,一次性存一次性读,强调读
  • 添加 set key value
  • 获取 get key
  • 删除 del key ...
  • 添加多个数据 mset k1 v1 k2 v2 ...
  • 获取多个数据 mget k1 k2
  • 字符个数 strlen key
  • 追加 append key value 不存在则新建

扩展操作

  • String中是数值,可以作为数值数据操作
incr num // +1
decr num // -1
incrby num increment // +increment
incrbyfloat num increment //增加小数
decrby num increment // -increment
  • 设置数据指定的生命周期,周期内可以进行加减操作
//设置秒 过了100秒数据不在
setex key seconds value
setex tel 100 10
//设置毫秒
psetex key milliseconds value

hash

image.png

  • map里放map,购物车、订单信息等
  • key对应的是一堆数据,而这堆数据的空间为hash,底层为hash表(红黑树+数组)
  • 添加
hset key field value
hset user name zhangsan
  • 添加多个
hmset key f1 v1 f2 v2...
hmset user name zhangsan weight 180
  • 获取
hget key field
hget user name
  • 获取多个
hmget k f1 f2..
hmget user name age weight
  • 获取全部
hgetall key
hgetall user
  • 删除
hdel key
hdel user name
  • 获取字段数量
hlen key
  • 是否存在指定字段
hexists key field

扩展操作

  • 获取指定key所有的field
hkeys key
hkeys user
  • 获取指定key所有的value
hvals key
hvals user
  • 增加数值,没有deincrby
hincrby key field increment
hincrby user age 1
//小数
hincrbyfloat key field increment
hincrbyfloat user age 19.2
  • 判断字段是否有值,有值则不修改,没有则新增
hsetnx key field value

list

image.png image.png

  • 时间特定;新增关注,时事新闻等
  • 存储多个数据,并对数据进入存储空间的顺序进行区分
  • 底层是双向链表
  • 添加数据
//从左向右,左边是开口,往右推 value1最右边 最后一个数据索引为1
lpush key value1 value2 ...
//从右向左,右边是开口,往左推 value1 最左边
rpush key value1 value2 ...
  • 获取数据
//从最左边开始获取数据
lrange key start stop
//查询到倒数第一个
lrange key 0 -1
//按数组索引取值
lindex key index
//查询倒数第一个
lindex key -1
//list长度
llen key
  • 获取并移除数据
//从最左边取出数据
lpop key
//从最右边取出数据
rpop key

扩展操作

  • 规定时间获取并移除数据,只要规定时间内能拿到数据就可以
blpop key seconds
brpop key seconds
  • 移除指定元素,移除中间元素
lrem key count value
//从name中移除两个wangwu
lrem name 2 wangwu

Set

image.png

  • 随机推荐热点信息,推荐类信息检索;同类型的数组去重,记录访问ip;黑白名单
  • 底层是hashmap,只使用key的位置存值,不允许重复
  • 不保证插入顺序
  • 便于查找
  • 添加数据
sadd key member1 member2...
  • 获取全部数据
smembers key
  • 删除数据
srem key member1 member2...
  • 获取集合数量
scard key
  • 判断集合中是否包含指定数据
sismember key member

扩展操作

  • 随机获取集合中的指定数量的数据,原集合数据不变
srandmember key [count]
  • 随机获取集合中的某个数据,并移除集合
spop key [count]
  • 两个集合的操作
//交集
sinter key1 [key2]
//存储到destination新集合中
sintersrote destination key1 [key2]
//并集
sunion key1 [key2]
sunionstore destination key1 [key2]
//差集 key2没有key1的部分
sdiff key1 [key2]
sdiffstore destination key1 [key2]
  • 将指定数据从原始集合中移动到目标集合中
//sourc数据来源集合,destination目标集合
smove source destination member

sorted_set

image.png

  • 股票涨势;一年工资;榜单数据;记录任务权重,由数字标记,每个类别长度要一样,如员工102和经理101,不能简单的为1或者2,要灵活补0
  • 根据自身特征进行排序
  • 不允许重复,会按照字符顺序排列
  • 在set的存储结构上添加可排序字段
  • score是一个双精度double值,如果加入的不是数值
ERR value is not a valid float
  • 添加数据
//score为被排序的内容,会根据这个字段进行排序
//member才是真正的值
zadd key score1 member1 score2 member2...
//zs 94分 ls 100分
zadd scores 94 zs 100 ls
  • 获取全部数据
//升序展示 有withscores会展示排序的字段内容
zrange key start stop [withscores]
//查看全部
zrange key 0 -1
//降序
zrevrange key start stop
  • 删除数据
zrem key member ...
  • 按条件获取数据
//升序
zrangebyscore key min max [withscores] [limit]
//查询50-80 之间的数据,按升序,显示分数,只显示前三个
zrangebyscore scores 50 80 withscores limit 0 3
//降序
zrevrangebyscore key max main [withscores] [limit]
  • 条件删除数据
//按索引
zremrangebyrank key start stop
//按照排名 升序 删除三个 0-2索引
zremrangebyrank scores 0 2
//按数值
zremrangebyscore key min max
//删除50-90之间的
zremrangebyscore scores 50 90
  • 获取集合数据总量
zcard key
zcount key min max
  • 集合操作
//numkeys 后面的集合数量
zinterstore destination numkeys key1 key2
//三个集合中求交集,并且相同的数据默认相加
zinterstore ss 3 s1 s2 s3
//三个集合中求交集,并且相同的数据求最小值
zinterstore sss 3 s1 s2 s3 aggregate min
//weights 权重 进行倍数后,再进行计算
zinterstore sss 3 s1 s2 s3 weights 2 3 4
//并集
zunionstore destination numkeys key1 key2

扩展操作

  • 获取数据对应的索引
//升序
zrank key mmeber
//降序
zrevrank key member
  • scare值获取与修改
zscore key member
zincrby key increment member

案例

  • 遇到需要检测次数的情况,例如只有十次机会,利用最大值-10,再通过incr增加,超过最大值报错的特点,进行自动判断
  • 微信会话顺序管理,利用set的不重复的特点存储置顶内容,两个list(栈形式,一端操作)分别存储普通和指定的消息队列进行排队 image.png
  • tips1 2 3 string
  • tips4 5 hash
  • tips5 6 list
  • tips8 9 10 11 12 set
  • tips 13 14 15 sorted_set

高级数据类型

Bitmaps

  • 操作二进制
  • 获取指定key对应偏移量上的bit值 getbit key offset
  • 设置 setbit key offset value value 只能是1或者0
  • 通过数量 bitcount key [start end]
  • 交、并、非、异或
//and or not xor
bitop op(操作) destkey(保存在这里) key1 [key2...]

HyperLogLog

  • 统计不重复的数量,基数(去重后的个数)统计
  • 存储的不是真实数据,只记录数量,核心是基数估算算法,最终数值存在误差(0.81%)
  • 每个使用12k上限的内存,会随着基数的增加内存逐渐增大,直到12k
  • 添加数据 pfadd key element [element ...]
  • 统计数据 pfcount key [key ...]
  • 合并统计 pfmerge destkey sourcekey [sourcekey ...],默认就是12k

GEO

  • 处理地理位置,只算水平位置
  • 添加坐标点 geoadd key longitude(经度) latitude member [....]
  • 获取坐标点 geopos key member [member ...]
  • 计算坐标点距离 geodist key member1 member2 [unit(单位默认是m,可以改成km)]
  • 根据坐标求范围内的数据 georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key] 以这个点为圆心,radius为半径画圆
  • 根据点求范围内的数据 georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key] 以这个成员为圆心,radius为半径画圆
  • 获取指定点对应坐标的hash值 geohash key member [member ...]

通用命令

key

  • 就是一个字符串
  • 删除指定key
del key
  • 获取key的类型
type key
  • 获取key是否存在
exists key

扩展操作

  • 为key设置有效期
expire key seconds
pexpire key milliseconds
//时间戳
expireat key timestamp
pexpireat key milliseconds-timestamp
  • 获取key的有效时间
//返回-1永久,返回-2过期,不存在
ttl key
//毫秒
pttl key
  • 切换key从有效性转换为永久性
persist key
  • 查询key
keys pattern
//查询所有key
keys *
? 匹配一个字符
[] 匹配一个指定字符

image.png

其他操作

  • 改名,newkey同名,则覆盖原来的内容
rename key newkey
//存在则不改
renamenx key newkey
  • 对key的内容排序
//只能操作list或者set,不会改变原集合的顺序
sort key
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]
  • 帮助
help @generic

数据库通用指令

  • 切换数据库
//默认16个 0-15
select index
  • 其他操作
quit
//测试服务器,连通的话返回PONG
ping
//客户端输出日志
echo message
  • 移动数据库
move key db
//把name移到0
move name 0
  • 数据清除
//查看有多少个key
dbsize
//删除当前库的数据
flushdb
//删除所有
flushall

发布与订阅

//订阅name的频道
subscribe name
//发布,往name的频道里发value
pulish name value

Jedis

  • java操作redis
  • 简单操作
//连接redis
Jedis jedis = new Jedis("127.0.0.1",6379);
//操作redis
//设置
jedis.set("name","wangwu");
//获取数据
String name = jedis.get("name");
System.out.println(name);
//关闭连接
jedis.close();
  • 方法与控制台上的差不多

hash

HashMap<String, String> map = new HashMap<>();
map.put("name","zhangsan");
map.put("age","18");
map.put("weight","68.7");
jedis.hmset("hash",map);
Map<String, String> hash = jedis.hgetAll("hash");
hash.forEach(new BiConsumer<String, String>() {
    @Override
    public void accept(String s, String s2) {
        System.out.println(s + "---" + s2);
    }
});

list

jedis.lpush("list", "a","b","c");
jedis.rpush("list", "a","b","c");
List<String> list = jedis.lrange("list", 0, -1);
for (String s : list) {
    System.out.println(s);
}

封装工具类

public class JedisUtils {
    private static String host;
    private static int port;
    private static int maxTotal;
    private static int maxIdle;
    private static JedisPool jp = null;
    static {
        ResourceBundle redis = ResourceBundle.getBundle("redis");
        host = redis.getString("redis.host");
        port = Integer.parseInt(redis.getString("redis.port"));
        maxTotal = Integer.parseInt(redis.getString("redis.maxTotal"));
        maxIdle = Integer.parseInt(redis.getString("redis.maxIdle"));
        JedisPoolConfig jpc = new JedisPoolConfig();
        jpc.setMaxTotal(maxTotal);
        //最大空闲数
        jpc.setMaxIdle(maxIdle);
        jp = new JedisPool(jpc, host, port);
    }
    public static Jedis getJedis() {
        return jp.getResource();
    }
}

redis启动

  • 服务端更换端口 redis-server --port 6380
  • 客户端连接 redis-cli -p 6380
  • 客户端指定ip -h

查看配置文件

  • 目录 /usr/local/ext
  • 配置文件 redis.conf
  • 通过配置文件启动
//复制一份
cat redis.conf  | grep -v "#" | grep -v "^$" > redis-6379.conf

//配置内容,修改配置文件
port 6379 //端口
daemonize no //后台启动,
logfile "" //日志文件,设置之后,在日志中显示,不显示在控制台
dir /usr/local/etc/data //存储的文件夹

//启动
redis-server redis-6379.conf

//复制一份 修改配置内容
cp redis-6379.conf redis-6380.conf

服务器基础配置

  • 设置服务器以守护进程的方式运行 daemoniz yes|no
  • 绑定主机地址 bind 127.0.0.1
  • 设置数据库数量 databases 16
  • 设置端口 port 6370

日志配置

  • 设置服务器以指定日志记录级别 loglevel debug(过程信息)|verbose(默认)|notice|warning
  • 日志记录文件名 logfile port.log

客户端配置

  • 设置最大客户端连接数 maxclients 0 0为不限制
  • 客户端限制最大时长,达到最大值后关闭连接 timeout 300(秒) 0关闭该功能

多服务器快捷配置

  • 导入并加载指定配置文件信息 include /path/server-port.conf,类似继承

持久化

  • 利用永久性存储介质将数据保存,例如硬盘,在特定的时间将保存的数据进行恢复的工作机制
  • 数据快照 RDB/过程日志 AOF

RDB

  • 存储效率高,存储的是某个时间点的数据,速度快,通常用于灾难恢复
  • 会丢数据,后台执行时,消耗子进程;redis版本rdb格式版本没有进行统一
  • save
  • 生成文件 dump.rdb
  • 文件保存在 /usr/local/etc/data
  • 配置
//文件名
dbfilename dump-6379.rdb
//是否压缩
rdbcompression yes
//rdb格式校验
rdbchecksum yes
  • save会阻塞当前服务器,不推荐线上使用

后台执行

  • bgsave,推荐使用
  • 调用fork函数生成子进程去保存
  • 保存结果会返回到控制台/日志文件
Background saving terminated with success
  • 配置,如果后台存储过程中出现错误,是否停止,默认开启
stop-writes-on-bgsave-error yes

自动执行

  • 对数据产生影响;真正产生了影响;不进行数据比对,产生一个影响量
  • 底层调用bgsave
  • 通过配置设置
//second 监控的时间范围;changes 监控key的变化量
save second changes
  • 日志信息
2 changes in 10 seconds. Saving...
Background saving started by pid 20409
DB saved on disk
Background saving terminated with success

image.png

特殊启动

  • 全量复制,主从复制
  • 服务器运行过程中重启 debug reload
  • 关闭服务器时指定保存数据 shutdown save

AOF

  • 记录操作过程,排除丢失数据的风险
  • append only file,以独立日志的方式记录
  • 先将操作命令放在AOP写命令刷新缓存区,在一定阶段后将命令同步到AOP文件中
  • 三种策略appendfsync
always 每次写入操作都同步到AOF文件中,数据零误差,性能差
everysec 每秒,数据准确定较高,性能高,但是突然宕机丢失一秒的数据
no 系统控制 由操作系统控制
  • 原理 image.png image.png

使用

  • 配置
//是否开启AOF持久化功能,默认不开启
appendonly yes|no
//AOF写数据策略
appendfsync always | everysec | no
//改文件名
appendfilename filename
//文件夹
dir

重写

  • 整理操作,提高磁盘利用率,降低持久化时间
  • 超时数据不写,忽略不对结果产生影响的指令,多条指令合并为一条指令
  • 手动重写 bgrewriteaof,重写后,就跟rdb形式一样的存储方式
  • 自动重写,配置
// 最小尺寸
auto-aof-rewrite-min-size size
// 自动重写的百分比
auto-aof-rewrite-precentage precentage
//重写条件
aof_current_size > auto-aof-rewrite-min-size
aof_cuuent_size - aof_base_size / aof_base_size >= auto-aof-rewrite-precentage

RDB和AOF的区别

image.png

事务

  • 开启事务 multi,之后的指令返回QUEUED
  • 执行事务 exec,执行所有指令
  • multi之后,后续所有的指令均加入到事务中,遇到exec之后,执行事务
  • 取消事务 discard
  • 如果后续输入的命令有语法错误,其余的命令都将不存在
  • 只要是语法正确,但是无法正确地执行,运行错误的命令将不会被执行

  • 监控数据 watch key1 key2...
  • 取消监控 unwatch
  • watch监控的数据,一旦被改变,如果下面开启事务,还未执行,将无法执行

分布式锁

  • 公共锁 setnx lock-key value,利用setnx命令的返回值特征,有值则返回设置失败,无值才能设置成功;操作完数据之后,del lock-key
  • 通过协议的方式实现,在操作数据前,先操作lock-key,如果可以操作,那么就可以操作,如果不行,就不操作
  • 为锁加上时间,防止忘记开锁 expire lock-key seconds

删除策略

  • 过期数据会被保留在redis中
  • 在内存中,为过期数据开辟一块hash的空间,管理过期数据 image.png

定时删除

  • 到期时间到时,cpu就去处理删除,用处理器性能换存储空间(时间换空间)

惰性删除

  • 数据到时不做处理,等下次访问该数据时,如果过期了,则清除,并返回不存在
  • expireIfNeeded()get key时执行
  • 节约CPU性能,内存压力大,用存储空间换取处理器性能(空间换时间)

定期删除

  • redis启动时,读取配置server.hz的值,默认为10,每秒钟执行server.hzserverCron()->databasesCron()->activeExpireCycle()
  • activeExpireCycle()对每个库的expires逐一检测,每次执行250ms/server.hz,对某个expires检测时,随机挑选W个key检测,如果key超时,则删除key;如果一轮中删除的key的数量>W*25%,证明过期数据较多,在检测一次;通过后,检查下一个
  • W取值 = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP属性值,配置文件中设置
  • current_db专门记录activeExpireCycle()进入到哪个库的expires空间执行
  • 每秒话费固定的CPU资源维护内存,随机抽查、重点抽查

逐出算法

  • redis使用内存存储数据,在执行每一个指令前,会调用freeMemoryIfNeeded()检测内存是否充足,如果不满足新加入数据的最低存储要求,根据逐出算法,临时删除一些数据
  • 最大可使用内存 maxmemory,占物理内存的比例,默认为0,不限制
  • 每次选取待删除数据的个数 maxmemory-samples,采用随机选取数据的方式
  • 删除策略 maxmemory-policy XXXXXX
  • lru 离现在的使用时间,淘汰最长的 image.png image.png

主从复制

  • 若干个redis连接在一起,保证数据是同步的,实现高可用,同时实现数据冗余备份
  • master 提供数据;slave 接收数据 image.png
  • 核心工作,就是master数据复制到slave
  • 一个master负责多个slave,一个slave只对应一个master
  • master只写,slave只读
  • master宕机,让某个slaver充当master
  • 主从复制实现读写分离、负载均衡、故障恢复、数据冗余、高可用
  • slave连接master,master将数据反复同步给slave

建立连接阶段

image.png

  • slave 发送 master的ip和端口号
slaveof ip port //客户端直接发送命令
redis-server -slaveof ip port //服务端启动发送
slaveof ip port //slave机器配置
//6380 连接 6379
slaveof 127.0.0.1 6379
//slave发送断开操作
slaveof no one
  • 权限验证
//slave端
auth password
masterauth password //配置文件
redis-cli -a password //启动设置密码
//master端
requirepass password //配置文件设置密码
config set requirepass password //命令设置密码
config get requirepass
  • 最后,slave保存了master的地址与端口;master保存了slave的端口;之间建立了连接的socket

数据同步阶段

  • 避开流量高峰期进行数据同步 image.png
  • 请求同步数据
  • 创建rdb同步数据
  • 恢复rdb同步数据
  • 请求部分同步数据,部分数据指的是全量复制过程中所产生的数据,也叫增量复制
  • 恢复部分同步数据
  • 最后状态,slave具有master端全部数据,包含rdb过程中接收的数据;master保存了slave当前同步的位置,下一次从上一次结尾开始复制
  • master 复制缓冲区,避免数据溢出 2平均时长数据总量
repl-backlog-size 1mb
  • slave只提供读,关闭写
slave-server-stable-date yes|no

命令传播阶段(不断同步)

  • 服务器运行ID,每一台服务器每次运行的身份识别码,40位字符组成,是一个随机的十六进制字符;用于在服务期间进行传输,身份识别,用于处理是否是一台机器,数据是否同步;info server查看runid;master在首次连接slave时,会将自己的运行id发送给slave,slave保存,并且每次更新都要携带,如果不同,则说明先前的master不是这个master
  • 复制缓冲区,是一个先进先出的队列,用于存储服务器执行过的命令,每次传播命令,master都会将传播的命令记录下来,存储在复制缓冲区;一条命令,以aof的形式存储,用字符为单位,存储字节值,并且给了一个编号(偏移量),用来识别;通过offset区分不同的slave当前数据传播的差异
  • 复制偏移量,一个数字,描述肤质缓冲区中的指令字节位置;master,发送一次记录一次,记录发给所有的slave的指令字节偏移量;slave,接收一次记录一次,记录自己接收master发过来的指令字节偏移量;作用,同步数据,对比差异

心跳机制

  • 命令传播阶段,master与slave间需要进行信息交换,使用心跳机制维护,保持双方在线 image.png
  • master处理策略,通过slave发送的REPLCONF ACK命令确定
//slave数量少于2个,或者所有slave的延迟都大于等于10秒,强制关闭master写功能,停止数据同步
min-slaves-to-write 2
min-slaves-max-lag 8

全部工作流程

image.png image.png

一些问题

image.png

  • 设置合理的超时时间
repl-timeout
  • ping指令发送频率,确定连接
repl-ping-slave-period
  • 如果slave延迟过大,多个slave获取相同数据不同步,暂时屏蔽对某个slave的数据访问;开启后仅响应info、slaveof等少数命令
slave-serve-stale-data yes|no

哨兵

  • 解决master宕机的问题
  • 在slave中选择一个作为master,通知所有的slave连接新的mater,启动新的master和slave
  • sentinel,分布式系统,用于对主从结构中的每台服务器进行监控,当master宕机,向哨兵间、客户端发送通知,选择出新的master,并将所有的slave连接到新的master上,并告诉客户端新的服务器地址,进行自动故障转移
  • 哨兵也是一台redis服务器,不提供数据服务,配置数量为单数
  • 配置sentinel.conf 配置相同,端口不同
//快速改端口,并复制一份
sed 's/26379/26381/g' sentinel-26379.conf > sentinel-26381.conf
  • 启动哨兵 redis-sentinel sentinel-端口号.conf
  • 整个过程在后台进行

监控

  • 同步信息
  • 同步各个节点状态信息,获取(ping)sentinel的状态,(info)master状态(runid、role、各个slave信息),(info)slave的信息 image.png

通知

  • 保持联通 image.png

故障转移

  • 判断master下线 image.png
  • 选择出一个sentinel负责选择新的master image.png
  • 选择新的master,选择在线的、响应快的、与原master断开时间短的、优先原则(优先级、offset、runid)
  • 向新的master发送slaveof no one 断开与原master的连接
  • 向其他slave发送 slaveof 新的masterIP和端口,建立新的连接

集群

  • 使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果
  • 分散单台服务器的访问压力,负载均衡;分散单台服务器的存储压力,可扩展性;降低单台服务器宕机带来的业务灾难

redis集群

  • 槽,存储key的位置
  • 通过算法设计,计算key应该保存的位置;增减服务器,处理槽的数量
  • 内部通讯设计,每台服务器互连,互相记录槽的位置;客户端一次命中,直接返回,一次未命中收到具体位置,直接去找

cluster集群

  • 配置
//设置是否是cluster
cluster-enabled yes
//配置文件名
cluster-config-file nodes-6379.conf
//超时时长 毫秒
cluster-node-timeout 10000
//master连接的slave最小数量
cluster-migration-barrier count
  • 建立,需要redis-trib.rb,配置ruby和gem环境
//执行前要对每个服务端执行
flushall
cluster reset
//执行命令,1代表一个master连一个slave,按后面添加的服务器自动分,而且服务器里面不允许有任何内容
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
  • 使用
//重定向启动,否则要在指定的端口槽中进行操作
redis-cli -c
//客户端查看节点状态
cluster nodes

主从下线和主从切换

  • 从下线/重连,直属master节点收到,并通知其他master节点
  • master节点下线,直属slave节点不断重连,超过超时时间后,变成mster
  • master节点重新连接,作为slave节点连接master

企业级解决方案

缓存预热

image.png

  • 系统启动前,提前将相关的缓存数据直接加载到缓存系统,避免在用户请求的时候,先查询数据库,然后再缓存,用户应该直接查询到事先准备好的缓存数据

缓存雪崩

  • 瞬间过期数据量太大,导致对数据库服务器造成压力,应该避免过期时间集中,监控服务器运行数据
  • 一个较短的时间内,缓存中较多的key集中过期,向数据库要
  • 数据库收到大量的请求无法及时处理,redis大量请求被积压,开始出现超时
  • 流量激增,资源严重被占用 image.png image.png

缓存击穿

  • 单个key高热或者过期,瞬间访问量大,没有命中redis,对数据库造成大量访问 image.png

缓存穿透

  • 访问不存在的数据
  • 数据库中不存在这个数据,reids中没有持久化;redis中大面积未命中,非正常的url访问 image.png

性能指标监控

  • 性能指标 Performance image.png
  • 内存指标 Memory image.png
  • 基本活动指标 Basic activity image.png
  • 持久性指标 Persistence image.png
  • 错误指标 Error image.png

监控命令

  • redis-benchmark
//-c 连接数 -n 请求数
redis-benchmark [-h] [-p] [-c] [-n <requests>] [-k]
//不带参数,50个链接 10000次请求对应的性能
//50个连接 100个请求
redis-benchmark -c 50 -n 100
  • 打印服务器调试信息 monitor,可以通过一个客户端来执行,看另一个客户端执行的语句
  • slowlog 慢查询日志,记录操作超时的命令
//获取慢查询日志/日志条目数/重置
slowlog get/len/reset

//相关配置
//设置慢查询的时间下线 微秒
slowlog-log-slower than 1000
//设置慢查询命令对应的日志显示长度 命令数
slowlog-max-len 100