Redis
Redis是什么
NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
- 基于内存运行,性能高效
- 支持分布式,理论上可以无限扩展
- key-value存储系统
- 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
相比于其他数据库类型,Redis具备的特点是:
- C/S通讯模型
- 单进程单线程模型
- 丰富的数据类型
- 操作具有原子性
- 持久化
- 高并发读写
- 支持lua脚本
Redis的应用场景
Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。
Redis的数据类型及主要特性
Redis提供的数据类型主要分为5种自有类型和一种自定义类型,这5种自有类型包括:String类型、哈希类型、列表类型、集合类型和顺序集合类型。
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 | LPOP 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 | SCAN cursor [MATCH pattern] [COUNT count] |
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击穿”。
引发击穿的原因:
- 第一次访问
- 恶意访问不存在的key
- Key过期
合理的规避方案:
- 服务器启动时, 提前写入
- 规范key的命名, 通过中间件拦截
- 对某些高频访问的Key,设置合理的TTL或永不过期
Redis常见问题解析:缓存雪崩
概念:Redis缓存层由于某种原因宕机后,所有的请求会涌向存储层,短时间内的高并发请求可能会导致存储层挂机,称之为“Redis雪崩”。
合理的规避方案:
- 使用Redis集群
- 限流