Redis

Redis是什么

NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:

  • 基于内存运行,性能高效
  • 支持分布式,理论上可以无限扩展
  • key-value存储系统
  • 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

相比于其他数据库类型,Redis具备的特点是:

  • C/S通讯模型
  • 单进程单线程模型
  • 丰富的数据类型
  • 操作具有原子性
  • 持久化
  • 高并发读写
  • 支持lua脚本

Redis的应用场景

Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。

image-20240910124045248

Redis的数据类型及主要特性

Redis提供的数据类型主要分为5种自有类型和一种自定义类型,这5种自有类型包括:String类型、哈希类型、列表类型、集合类型和顺序集合类型。

image-20240910124109018

image-20240910141319069

String类型

它是一个二进制安全的字符串,意味着它不仅能够存储字符串、还能存储图片、视频等多种类型, 最大长度支持512M。

操作命令

  • GET/MGET

  • SET/SETEX/MSET/MSETNX

  • INCR/DECR

  • GETSET

  • DEL

  • 设置键的值 - SET

    1
    SET key1 "hello"  
  • 获取键的值 - GET

    1
    GET key1
  • 设置键的值并设置过期时间(单位为秒) - SETEX

    1
    SETEX key2 10 "world"  
  • 获取键的值并同时设置新值 - GETSET

    1
    GETSET key2 "new value"  
  • 返回键值的子字符串 - GETRANGE

    1
    GETRANGE key2 0 2  
  • 给键的值追加新值 - APPEND

    1
    APPEND key1 " Redis"  
  • 获取多个键的值 - MGET

    1
    MGET key1 key2 key3  
  • 设置多个键值对 - MGET

    1
    MSET key4 "apple" key5 "banana" key6 "orange"  
  • 自增键的值 - INCR

    1
    INCR key7  
  • 自减键的值 - DECR

    1
    DECR key7  
  • 删除单个键 - DEL

    1
    DEL key1  
  • 删除多个键 - DEL

    1
    DEL key2 key3 key4  
哈希类型

该类型是由field和关联的value组成的map。其中,field和value都是字符串类型的。

操作命令

  • HGET/HMGET/HGETALL
  • HSET/HMSET/HSETNX
  • HEXISTS/HLEN
  • HKEYS/HDEL
  • HVALS
  • 设置哈希表的字段值 - HSET

    1
    HSET myhash field1 "value1"
  • 获取哈希表的字段值 - HGET

    1
    HGET myhash field1  
  • 获取哈希表中所有字段和值 - HGETALL

    1
    HGETALL myhash 
  • 删除哈希表中一个或多个字段 - HDEL

    1
    HDEL myhash field1 field2  
  • 检查哈希表中是否存在某个字段 - HEXISTS

    1
    HEXISTS myhash field1  
  • 获取哈希表中所有字段 - HKEYS

    1
    HKEYS myhash  
  • 获取哈希表中所有值 - HVALS

    1
    HVALS myhash  
  • 给哈希表中字段值增加指定数值 - HINCRBY

    1
    HINCRBY myhash field1 10  
列表类型

该类型是一个插入顺序排序的字符串元素集合, 基于双链表实现。

  • LPUSH/LPUSHX/LPOP/RPUSH/RPUSHX/RPOP/LINSERT/LSET
  • LINDEX/LRANGE
  • LLEN/LTRIM
  • 向列表的头部插入一个或多个值 - LPUSH
1
LPUSH mylist value1 value2  
  • 向列表的尾部插入一个或多个值 - RPUSH
1
RPUSH mylist value3 value4  
  • 获取列表指定范围的值 - LRANGE
1
LRANGE mylist 0 -1  
  • 获取列表指定索引位置的值 - LINDEX
1
LINDEX mylist 0  
  • 弹出并返回列表头部或尾部的值 - LPOP/RPOP
1
2
LPOP mylist  
RPOP mylist
  • 获取列表的长度 - LLEN
1
LLEN mylist  
  • 移除列表中指定值的元素 - LREM
1
LREM mylist 0 value1  
  • 截取列表中指定范围的值 - LTRIM
1
LTRIM mylist 0 2  
集合类型

Set类型是一种无顺序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的。Set类型的底层是通过哈希表实现的

操作命令

  • SADD/SPOP/SMOVE/SCARD

  • SINTER/SDIFF/SDIFFSTORE/SUNION

  • 向集合添加一个或多个成员 - SADD

1
SADD myset member1 member2  
  • 获取集合的所有成员 - SMEMBERS
1
SMEMBERS myset  
  • 检查集合中是否存在某个成员 - SISMEMBER
1
SISMEMBER myset member1  
  • 从集合中移除一个或多个成员 - SREM
1
SREM myset member1  
  • 返回集合元素的数量 - SCARD
1
SCARD myset  
  • 返回随机的集合成员 - SRANDMEMBER
1
SRANDMEMBER myset  
  • 返回两个集合的交集 - SINTER
1
SINTER set1 set2  
  • 返回两个集合的并集 - SUNION
1
SUNION set1 set2  
有序集合类型

ZSet是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与Set类型一样,其底层也是通过哈希表实现的。

  • ZADD/ZPOP/ZMOVE/ZCARD/ZCOUNT
  • ZINTER/ZDIFF/ZDIFFSTORE/ZUNION

向有序集合添加一个成员及其分数:

1
ZADD myzset 1 "member1"  

获取有序集合指定成员的分数:

1
ZSCORE myzset "member1"  

获取有序集合指定排名范围内的成员:

1
ZREVRANGE myzset 0 -1  

获取有序集合指定分数范围内的成员:

1
ZRANGEBYSCORE myzset 0 10  

计算有序集合中成员的排名:

1
ZRANK myzset "member1"  

移除有序集合中的一个或多个成员:

1
ZREM myzset "member1"  

计算有序集合中成员的数量:

1
ZCARD myzset  

计算有序集合中指定分数范围内成员的数量:

1
ZCOUNT myzset 0 10  
查找某个详细的键是否存在
1
EXISTS key_name  
  • 返回值:
    • 1 - 键存在
    • 0 - 键不存在
模糊查找某个键

使用 KEYS 命令可以查找具有特定模式的所有键。请注意,KEYS 命令在生产环境中不推荐使用,因为在大量数据时会影响性能。
SCAN 命令是更高效的方法、尤其是当键的数量很多时。它以游标的方式进行增量迭代。

1
2
3
SCAN cursor [MATCH pattern] [COUNT count]  
eg: 以 my_ 开头的键,并且每次返回最多 10 个结果
SCAN 0 MATCH my_* COUNT 10

Redis特性1:事务

  • 命令序列化,按顺序执行
  • 原子性
  • 三阶段: 开始事务 - 命令入队 - 执行事务
  • 命令:MULTI/EXEC/DISCARD

Redis特性2:发布订阅(Pub/Sub)

  • Pub/sub是一种消息通讯模式
  • Pub发送消息, Sub接受消息
  • Redis客户端可以订阅任意数量的频道
  • “fire and forgot”, 发送即遗忘
  • 命令:Publish/Subscribe/Psubscribe/UnSub

Redis特性3:Stream

  • Redis 5.0新增
  • 等待消费
  • 消费组(组内竞争)
  • 消费历史数据
  • FIFO

Redis常见问题解析:缓存击穿

概念:在Redis获取某一key时, 由于key不存在, 而必须向DB发起一次请求的行为, 称为“Redis击穿”。

image-20240910141558660

引发击穿的原因:

  • 第一次访问
  • 恶意访问不存在的key
  • Key过期

合理的规避方案:

  • 服务器启动时, 提前写入
  • 规范key的命名, 通过中间件拦截
  • 对某些高频访问的Key,设置合理的TTL或永不过期

Redis常见问题解析:缓存雪崩

概念:Redis缓存层由于某种原因宕机后,所有的请求会涌向存储层,短时间内的高并发请求可能会导致存储层挂机,称之为“Redis雪崩”。

合理的规避方案:

  • 使用Redis集群
  • 限流