1 Redis 是单线程的协议简单(resp)简单稳定
基于内存的支持持久化( 默认 是rdb) key-value型高性能缓存数据库 主从复制,数据存储在内存 支持 5种主要的数据结构
(1)String 字符串类型
(2) Hash 类型
(3) List (队列)
(4) Set / Zset 有序集合 一个集合 最大有 2的 32次方 - 1 个元素
exists user:1001 检查到键是否cunz; sadd key001 u1 添加相同的值 是结果返回 0 不能重复
srem key001 u1 删除值 scard key001 计算集合元素的个数
使用场景:缓存数据;计数,消息队列等
resp 协议 (1) 实现简单 (2)解析快速 (3)人类可读
String 类型 (1) set 单个设值 (2)mset 批量设值
自增 incr article:1001 get article:1001
生成分布式序列号 incrby article:101(key) 100(生成序列的步长) re
redis弱事务 multi 开启事务 exec 提交事务 discard 取消事务
语法错误 事务自动异常中断
multi 事务开始
sadd key member
exec 事务执行结束
这个就是弱事务 并没有回滚
watch 监听 key 前面的窗口使用 watch 后 事务失效 exec 提交事务的会为空 提交事务失败,所以 get key 的时候是 后面窗口的数据
发布订阅简单的
redis 键迁移 / 选择数据库命名
dump key 序列化 键 ,恢复 数据
migrate 迁移数据 实际上 migrate 命令将 dump / resore / del 三个命令的组合,该命令具有原子性 从 redis 3.0.6 后开始支持多个键迁移,目标redis 完成 restore 后会给源redis 发送 OK
格式如下:
migrate | 192.168.0.103 | 6379 | key001 | 0 | 1000 | copy | replace |
指令 | 目标redis 服务IP | 目标端口 | 迁移键 | 目标库 | 超时时间 | 迁移和不删除源键 | 不管目标库是否存在 键都迁移成功 |
例如:192.168.0.105:6379>migrare 192.168.0.103 6379 key001 0 1000 copy
scan 遍历匹配
1> 通过游标分布查询,不会 阻塞线程 提供 limit 参数 可以控制返回结果的最大条数 limit 不准 返回结果可多可少
2> 遍历查询结果会有重复,需要客户端去重,而且 修改后的数据 可能遍历出是不确定
3> 单次返回结果为空 并不一定遍历结束,需要看返回的游标是否为0
keys 会阻塞线程
>>> hash 存储 当某个键的值大于阈值时512m 会转码成 hashtable 编码更耗内存
hmset user:101 name deer age 18
hgetall user:101
hincrby cart:100 (key) product:1001 2
购物车的产品数量 加1
setnx key001 value00s
>>>>> List 队列
(1) 实现阻塞队列 (有数据时弹出执行业务) lpush + brpop
(2) 实现栈 (先进后出) lpush + lpop
(3) 实现队列(先进先出) lpush + rpop
案例1: 微信公众号推送 set
lpush message:1001 user100121 lpush message:1001 user100121 lpush message:1001 user100121
查询所有
获取索引位: lindex key001 0(index) llen key001 列表长度
案例2:抽奖 set sadd activity:1001 u10001 u10002 u10003 活动参加的用户
随机抽取一名用户 srandmemeber activity:1001 0 1
获取活动参与的所有用户: smembers activity:1001
示例3:用户 u101 u102 同时感兴趣的
sunion 看两个键的合集
sdiff k1 k2 查看 k1 对比 k2 的差集
zset 有序集合 用户排行榜 设值一个评分字段
zadd rank01 c 99 100 java 102 php
zrange rank01 0 -1 withscores 查看分数和成员
zrank rank01 java 查看名次(从 0开始)
zrevrank rank01 java
缓存雪崩:
(1)大量的 键 同时失效导致大量的请求同时请求到数据库导致 (分散设值 键的失效时间)
(2)一个键 失效(没有采取措施) 大量的请求同时请求到数据库导致 (不存在的key 或者 key 失效 后采用 锁机制确保只有一个请求请求到数据库)布隆过滤器
lua 脚本执行可以确保 操作的原子性(全部操作要么一次性成功,要么就全失败)
缓存穿透 说的是 缓存中没有数据数据库中存在数据
缓存击穿 说的是 缓存和数据库中均不存在数据
并发环境下 同一个key会出现竞态条件
3. 主从拓扑结构
缺点:一旦主节点宕机 需要修改后端代码,做不到高可用
4. 持久化
RDB 持久化 把当前进程中的数据生成快照文件(.rdb)保存到磁盘 分为 手动触发 和 自动触发
- 手动触发 指令 save 和 bgsave
- save 指令 阻塞 redis 直到 rdb 持久化过程结束 若数据较多 阻塞时间会很长 生产环境不建议使用
- bgsave redis进程执行 fork 操作 创建子进程来完成持久化 阻塞时间短暂(微秒级) 在执行 redis-cli shutdown 关闭 redis 服务时,如果没有开启 AOF持久化 则自动执行bgsave指令
rdb 文件存储的是数据 不支持实时持久化
- 一次性的设置文件保存路径 config set dir /home/softs/data/redis
- 压缩后的二进制文件适合备份全量拷贝,用于灾备恢复,恢复数据速度快于AOF;保存后的二进制文件存在不兼容老版本 rdb 文件问题
AOF 持久化 保存的执行的指令 恢复的时候 还需要再次解析编译转换就要慢
- 启用AOF appendonly yes
- 收到命令立即写入到磁盘 最安全 appendfsync always (不推荐)
- appendfsync everysec 每秒强制写入磁盘一次,综合评估的做法 (推荐)
- no-appendfsync-on-rewrite yes 正在导出 rdb 快照文件过程中 是否停止同步 aof
- auto-aof-rewrite-percentage 100 aof 文件对比最近一次重写的大小增长的比率 100%时重新压缩 如:上一次 80MB 此次 160MB
- auto-aof-rewrite-min-size 64mb aof 文件至少达到64MB 才重新压缩
redis 重启会自动加载 aof文件
- redis启动会首先检查是否开启了 AOF 开启了 加载AOF文件 如果AOF文件不存在 看是否有rdb 文件有则加载 rdb 文件
- 如果没开启 AOF 则加载 rdb 文件
高可用-哨兵
哨兵节点个数最好设置为奇数个,投票选举, 哨兵机制采用 Raft算法进行 leader 的选举 Raft算法的(先发现大概率抢占leader; 少数服从多数)