当前位置: 首页>后端>正文

14-redis

前言

questions:
1、缓存有哪些类型
2、缓存的读写模式
3、缓存的数据结构

Redis应用场景

  • 缓存使用,减轻DB压力
  • DB使用,用于临时存储数据(字典表,购买记录)
  • 解决分布式场景下Session分离问题(登录信息)
  • 任务队列(秒杀、抢红包等等) 乐观锁(watch + incr)
  • 应用排行榜 zset
  • 签到 bitmap
  • 分布式锁
  • 冷热数据交换

缓存可能存在的问题:

  • 高并发场景下会出现缓存失效(缓存穿透、缓存雪崩、缓存击穿)
  • 缓存与数据库无法做到数据的时时同步
  • Redis无法做到主从时时数据同步
  • 缓存并发竞争
    多个redis的客户端同时对一个key进行set值得时候由于执行顺序引起的并发问题(???没get到啊)

缓存穿透
是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

缓存击穿
是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

缓存雪崩
是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

1. redis的数据类型和命令

Redis是一个Key-Value的存储系统,key的类型是字符串。
value的数据类型有:
常用的:string字符串类型、list列表类型、set集合类型、sortedset(zset)有序集合类型、hash类型。
不常见的:bitmap位图类型、geo地理位置类型。
Redis5.0新增一种:stream类型(可以用来做消息队列)

1.1 字符串类型

Redis的String能表达3种值的类型:字符串、整数、浮点数 100.01 是个六位的串

命令:

  • set :set key value 赋值
  • get: get key 取值
  • getset: getset key value 取值并赋值
  • setnx :setnx key value 当key不存在时才用赋值
  • set key value NX PX 3000 (原子操作,px 设置毫秒数)
  • append: append key value 向尾部追加值
  • strlen: strlen key 获取字符串长度
  • incr :incr key 递增数字
  • incrby: incrby key increment 增加指定的整数
  • decr: decr key 递减数字
  • decrby: decrby key decrement 减少指定的整数
    应用场景:缓存,分布式锁

1.2 list列表类型

list列表类型可以存储有序、可重复的元素
不完全命令:(着重记一下)

  • lpush: lpush key v1 v2 v3 ...(从左侧插入列表)
  • lpop: lpop key (从列表左侧取出)
  • rpush: rpush key v1 v2 v3 ... (从右侧插入列表)
  • rpop: rpop key (从列表右侧取出)
  • lpushx: lpushx key value (将值插入到列表头部)
  • rpushx: rpushx key value (将值插入到列表尾)
    ps:我还没意识到list真正有用的点在哪,下面这个是讲义上写的,融我再领会领会吧
    应用场景:
    1、作为栈或队列使用
    列表有序可以作为栈和队列使用
    2、可用于各种列表,比如用户列表、商品列表、评论列表等

1.3 Set

Set:无序、唯一元素
命令:

  • sadd: sadd key mem1 mem2 .... 为集合添加新成员
  • srem: srem key mem1 mem2 .... 删除集合中指定成员
  • smembers: smembers key 获得集合中所有元素
  • spop: spop key 返回集合中一个随机元素,并将该元素删除
  • srandmember: srandmember key 返回集合中一个随机元素,不会删除该元素
  • scard: scard key 获得集合中元素的数量
  • sismember: sismember key member 判断元素是否在集合内
  • sinter: sinter key1 key2 key3 求多集合的交集
  • sdiff: sdiff key1 key2 key3 求多集合的差集
  • sunion: sunion key1 key2 key3 求多集合的并
14-redis,第1张
set的两种编码

适用场景:
关注的用户,通过spop进行随机抽奖等

1.4 sortedset有序集合类型

元素本身是无序不重复的,每个元素关联一个分数(score),可按分数排序,分数可重复
命令:

  • zadd: zadd key score1 member1 score2 member2 ... 为有序集合添加新成员
  • zrem zrem key mem1 mem2 .... 删除有序集合中指定成员
  • zcard zcard key 获得有序集合中的元素数量
  • zcount zcount key min max 返回集合中score值在[min,max]区间的元素数量
  • zincrby zincrby key increment member 在集合的member分值上加increment
  • zscore zscore key member 获得集合中member的分数
  • zrank zrank key member 获得集合中member的排名(按分值从小到大)
  • zrevrank zrevrank key member 获得集合中member的排名(按分值从大到小)
  • zrange zrange key start end 获得集合中指定区间成员,按分数递增排序
  • zrevrange zrevrange key start end 获得集合中指定区间成员,按分数递减排序
    应用场景:
    由于可以按照分值排序,所以适用于各种排行榜。比如:点击排行榜、销量排行榜、关注排行榜等。

1.5 hash类型(散列表)

Redis hash 是一个 string 类型的 field 和 value 的映射表,它提供了字段和字段值的映射
命令:

  • hset: hset key field value 赋值,不区别新增或修改
  • hmset: hmset key field1 value1 field2 value2 批量赋值
  • hsetnx: hsetnx key field value 赋值,如果filed存在则不操作
  • hexists hexists key filed 查看某个field是否存在
  • hget: hget key field 获取一个字段值
  • hmget hmget key field1 field2 ... 获取多个字段值
  • hgetall hgetall key
  • hdel hdel key field1 field2... 删除指定字段
  • hincrby hincrby key field increment 指定字段自增increment
  • hlen hlen key 获得字段数
    应用场景:
    对象的存储 ,表数据的映射

2 redis扩展

2.1 发布和订阅

Redis提供了发布订阅功能,可以用于消息的传输
Redis的发布订阅机制包括三个部分,publisher,subscriber和Channel
发布者和订阅者都是Redis客户端,Channel则为Redis服务器端。
发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。

14-redis,第2张
发布订阅

命令:
subscribe:订阅 subscribe channel1 channel2..
publish:发布消息 publish channel messag
unsubscribe:退订 channel
使用场景:哨兵模式、Redisson框架使用
  • 在Redis哨兵模式中,哨兵通过发布与订阅的方式与Redis主服务器和Redis从服务器进行通信。
  • Redisson是一个分布式锁框架,在Redisson分布式锁释放的时候,是使用发布与订阅的方式通知的(参考链接6)

2.2 redis事务

  • Redis的事务是通过multi、exec、discard、watch这四个命令来完成的。
  • Redis的单个命令都是原子性的,所以这里需要确保事务性的对象是命令集合。
  • Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行
  • Redis不支持回滚操作

2.2.1 事务命令

multi:用于标记事务块的开始,Redis会将后续的命令逐个放入队列中,然后使用exec原子化地执行这个命令队列。RedisClient将命令存放在事务队列中(EXEC,DISCARD,WATCH,MULTI除外)
exec:执行命令队列
discard:清除命令队列
watch:监视key
unwatch:清除监视key

Redis WATCH 命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到 EXEC 命令。(链接8,更详细的watch介绍参考链接9)

事务可以用来实现乐观锁。

3 redis核心原理

3.1 aof和rdb

Redis持久化是为了快速的恢复数据而不是为了存储数据
Redis有两种持久化方式:RDB和AOF
注意:Redis持久化不保证数据的完整性。

3.1.1 RDB

RDB(Redis DataBase),是redis默认的存储方式,RDB方式是通过快照( snapshotting )完成的。
RDB的优缺点

  • 优点
    RDB是二进制压缩文件,占用空间小,便于传输(传给slaver)
    主进程fork子进程,可以最大化Redis性能,主进程不能太大,Redis的数据量不能太大,复制过程中主进程阻塞
  • 缺点
    不保证数据完整性,会丢失最后一次快照以后更改的所有数据

3.1.2 AOF

AOF(append only file)是Redis的另一种持久化方式。Redis默认情况下是不开启的。开启AOF持久化后,Redis 将所有对数据库进行过写入的命令(及其参数)(RESP)记录到 AOF 文件, 以此达到记录数据库状态的目的,
当Redis重启后只要按顺序回放这些命令就会恢复到原始状态了。
AOF会记录过程,RDB只管结果

AOF原理
AOF文件中存储的是redis的命令,同步命令到 AOF 文件的整个过程可以分为三个阶段:
1、命令传播:Redis 将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中。
2、 缓存追加:AOF 程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中。
3、文件写入和保存:AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存条件被满足的话,fsync 函数或者 fdatasync 函数会被调用,将写入的内容真正地保存到磁盘中

3.1.3 aof重写 和 混合模式

aof重写:Redis可以在 AOF体积变得过大时,自动地在后台(Fork子进程)对 AOF进行重写。重写后的新 AOF文件包含了恢复当前数据集所需的最小命令集合。 所谓的“重写”其实是一个有歧义的词语, 实际上,AOF 重写并不需要对原有的 AOF 文件进行任何写入和读取, 它针对的是数据库中键的当前值。

Redis数据库里的+AOF重写过程中的命令------->新的AOF文件---->覆盖老的
当步骤 1 执行完毕之后, 现有 AOF 文件、新 AOF 文件和数据库三者的状态就完全一致了。
当步骤 2 执行完毕之后, 程序就完成了新旧两个 AOF 文件的交替。

混合模式
RDB和AOF各有优缺点,Redis 4.0 开始支持 rdb 和 aof 的混合持久化。如果把混合持久化打开,aof rewrite 的时候就直接把 rdb 的内容写到 aof 文件开头。
RDB的头+AOF的身体---->appendonly.aof

3.2 底层数据结构

14-redis,第3张
底层结构
typedef struct redisDb {
int id; //id是数据库序号,为0-15(默认Redis有16个数据库)
long avg_ttl; //存储的数据库对象的平均ttl(time to live),用于统计
dict *dict; //存储数据库所有的key-value
dict *expires; //存储key的过期时间
dict *blocking_keys;//blpop 存储阻塞key和客户端对象
dict *ready_keys;//阻塞后push 响应阻塞客户端 存储阻塞后push的key和客户端对象
dict *watched_keys;//存储watch监控的的key和客户端对象
} redisDb;

ps:blocking_keys和ready_keys是啥
整个数据放在dict的字典里,dict是一个数组.

3.2.1 简单动态字符串 SDS

3.2.2 链表

3.2.3 字典(hashtable)

3.2.4 跳跃表

3.2.5 整数集合

3.2.6 压缩列表

ps:参考链接11

3.3 通讯协议和事件处理机制

通讯协议后面再补吧,现在level有点不够...

3.3.1 文件事件

14-redis,第4张
事件处理机制

3.3.2 时间事件

好吧,涉及到了读源码了...

4 企业实战

4.1 缓存问题

缓存击穿
缓存穿透
缓存雪崩

4.2 分布式锁的方案

incr + watch实现乐观锁
setnx
redisson
redlock

4.3 高可用方案

4.3.1 主从复制

要用到aof实现主从同步

4.3.2 哨兵模式

哨兵(sentinel)可以监视主从服务器,当主服务器下线后,会将对应的从服务器升级为主服务器,保证高可用

4.3.3 集群和分区

Redis3.0之后,推荐官方cluster分区。
RedisCluster方案采用去中心化的方式,包括:sharding(分区)、replication(复制)、failover(故障转移)
Redis5.0可以直接使用Redis-cli进行集群的创建和管理

链接们:
1、Ehcache与Memcache的区别
2、zk实现分布式锁
3、redis的文件事件和时间事件
4、redis的红锁
5、redis实现乐观锁
6、redisson分布式锁
7、redis的事务和watch
8、redis的watch
9、redis的watch,
10、redis的底层结构
11、redis 20道经典面试题
12、redis时间事件(解读源码)
13、JedisCluster原理
14、Redis数据过期和淘汰策略详解

关于作业
1、虚拟机老是报磁盘空间不足:https://jingyan.baidu.com/article/a681b0de60d9263b19434665.html
2、重新启动redis 参考的 06-分布式和集群 https://www.jianshu.com/p/585b49c99057
(我自己安装的redis的路径为:cd redis-6.0.3/src/)
3、清空redis下的数据:https://blog.csdn.net/weixin_39518840/article/details/112023443


https://www.xamrdz.com/backend/3z41939634.html

相关文章: