初识Redis
- 关系型数据库:mysql、oracle (数据之间有关联关系【主键与外键】、数据存储在硬盘的文件上)
- 非关系型数据库(NoSql):Redis、hbase(数据之间没有关联关系、数据存储在内存中)
什么是 NoSQL?
- SQL: 结构化数据,使用关系型数据库。
- NoSQL: 非结构化数据,支持多种数据模型。
认识 Redis
Redis,全称为 Remote Dictionary Server(远程词典服务器),于 2009 年诞生,是C语言开发的一种基于内存的键值型 NoSQL 数据库。
Redis 的特点
- 键值存储: 支持多种数据结构。
- 单线程无锁: 每个命令具备原子性,避免线程切换开销。
- 低延迟: 基于内存读写,速度快,比磁盘数据库快100倍。
- 数据持久化: 支持将数据保存到硬盘。
- 集群支持: 支持主从复制和分片,轻松支撑百万QPS。
- 多语言客户端: 可通过多种编程语言访问。
redis的应用场景
- 缓存(数据查询、短连接、新闻内容、商品内容等等)
- 聊天室的在线好友列表
- 任务队列。(秒杀、抢购、12306等等)
- 应用排行榜
- 网站访问统计
- 数据过期处理(可以精确到亳秒分布式集群架构中的session分离)
安装Redis
可以通过 Docker 在虚拟机上安装 Redis。
命令行客户端
redis-cli [options] [commands]
常见options:
- -h 127.0.0.1: 指定 Redis 节点 IP(默认 127.0.0.1)。
- -p 6379: 指定 Redis 节点端口(默认 6379)。
- -a 123321: 指定访问密码。
常用命令
- PING: 测试与 Redis 服务的连接。
- AUTH username password: 登录连接(若无用户名,直接写密码)。
- redis-cli shutdown: 关闭单实例。
- redis-cli -p 6379 shutdown: 关闭指定端口的多实例。
📦Redis常见命令
Redis 数据结构
Redis 是一个 key-value 数据库,支持多种 value 类型。
常见命令学习
可以在 Redis 命令文档( https://redis.io/commands ) 查询各类命令,也可使用 help 命令在客户端查看,help @generic(查看通用命令)、help @String(查看string帮助命令)、…。
通用命令
通用命令适用于多种数据类型,常见的有:
- KEYS:列出符合模式的所有键,不建议在生产环境设备上使用
- **keys ***:查看所有键
- keys a*:查看所有以a开头的键
- DEL:删除指定的key(后面可跟多个key,空格分隔,返回值为成功删除的key的个数)
- EXISTS:判断key是否存在
- EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
- TTL KEY:查看一个KEY的剩余有效期
通过help [command] 可以查看一个命令的具体用法。
redis 127.0.0.1:6379> keys *
1) "mysort"
2) "username"
3) "myhash"
4) "mylist"
5) "myset"
redis 127.0.0.1:6379> type username
string
1.String(万能钥匙)
String 类型是 Redis 中最简单的存储类型。其值为字符串,分为三类:
- 普通字符串: string
- 整数: int(支持自增、自减)
- 浮点数: float(支持自增、自减)
底层存储为字节数组,最大空间为 512MB。
常见命令
- SET:添加或修改字符串键值对。
- GET:获取指定键的值
- MSET:批量添加多个键值对。
- MGET:批量获取多个键的值。
- INCR:让一个整型的key自增1
- INCRBY:让一个整型的key自增并指定步长,例如:incrby num 2 让num值自增2
- INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
- SETNX:添加键值对,仅在键不存在时执行。
- SETEX:添加键值对并指定有效期。
redis 127.0.0.1:6379> set username zhangsan
OK
redis 127.0.0.1:6379> get username
"zhangsan"
redis 127.0.0.1:6379> del age
(integer) 1
redis 127.0.0.1:6379> get age
(nil)
2. Hash(对象存储)
Hash 类型是一个无序字典,类似于 Java 中的 HashMap。它允许将对象的字段独立存储,便于对单个字段进行 CRUD 操作。
常见命令
- HSET key field value:添加或修改哈希字段的值。
- HGET key field:获取哈希字段的值。
- HMSET:批量添加多个hash字段的值。
- HMGET:批量获取多个hash字段的值。
- HGETALL:获取哈希中所有字段和值。
- HKEYS:获取哈希中的所有字段。
- HVALS:获取一个hash类型的key中的所有的value
- HINCRBY:让一个hash类型key的字段值自增并指定步长
- HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行
redis 127.0.0.1:6379> hset myhash username lisi
(integer) 1
redis 127.0.0.1:6379> hset myhash password 12
(integer) 1
redis 127.0.0.1:6379> hget myhash username
"lisi"
redis 127.0.0.1:6379> hgetall myhash
1) "username"
2) "lisi"
3) "password"
4) "12"
redis 127.0.0.1:6379> hdel myhash username
(integer) 1
redis 127.0.0.1:6379> hget myhash username
(nil)
3. List(消息队列)
List 类型类似于 Java 中的 LinkedList,是一个双向链表结构。支持正向和反向检索。
特点
- 有序
- 元素可以重复
- 插入和删除速度快
- 查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
常见命令:
- **LPUSH key val1 val2 ** … :向列表左侧插入一个或多个元素
- LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
- RPUSH key element … :向列表右侧插入一个或多个元素
- RPOP key:移除并返回列表右侧的第一个元素
- LRANGE key star end:返回一段角标范围内的所有元素
- BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
redis 127.0.0.1:6379> lpush mylist a
(integer) 1
redis 127.0.0.1:6379> lpush mylist b
(integer) 1
redis 127.0.0.1:6379> rpush mylist c
(integer) 3
---- 0左边第一个,-1右边第一个,(0-1表示获取所有)
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "b"
2) "a"
3) "c"
redis 127.0.0.1:6379> lpop mylist
"b"
redis 127.0.0.1:6379> rpop mylist
"c"
4. Set(社交神器)
Set 类型与 Java 中的 HashSet 类似,是一个无序且不重复的元素集合。
特点:
- 无序
- 元素不可重复
- 查找快
- 支持交集、并集、差集等操作
常见命令
- SADD key member … :向set中添加一个或多个元素
- SREM key member … : 移除set中的指定元素
- SCARD key: 返回set中元素的个数
- SISMEMBER key member:判断一个元素是否存在于set中
- SMEMBERS:获取set中的所有元素
- SINTER key1 key2 … :求key1与key2的交集
- SDIFF key1 key2 … :求key1与key2的差集
- SUNION key1 key2 …:求key1和key2的并集
redis 127.0.0.1:6379> sadd myset a
(integer) 1
redis 127.0.0.1:6379> sadd myset a
(integer) 0
redis 127.0.0.1:6379> smembers myset
1) "a"
5.Sorted Set(排行榜)
Sorted Set 是一个可排序的集合,每个元素都有一个 score 属性,用于排序,底层的实现是一个跳表(SkipList)加 hash表。
特点:
- 可排序
- 元素不重复
- 查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
常见命令
- ZADD key score member:添加一个或多个元素到sorted set ,如果已经存在则更新其score值
- ZREM key member:删除sorted set中的一个指定元素
- ZSCORE key member : 获取sorted set中的指定元素的score值
- ZRANK key member:获取sorted set 中的指定元素的排名
- ZCARD key:获取sorted set中的元素个数
- ZCOUNT key min max:统计score值在给定范围内的所有元素的个数
- ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的increment值
- ZRANGE key min max:按照score排序后,获取指定排名范围内的元素
- ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素
- ZDIFF、ZINTER、ZUNION:求差集、交集、并集
注意事项:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可
redis 127.0.0.1:6379> zadd mysort 60 zhangsan
(integer) 1
redis 127.0.0.1:6379> zadd mysort 50 lisi
(integer) 1
redis 127.0.0.1:6379> zadd mysort 80 wangwu
(integer) 1
redis 127.0.0.1:6379> zrange mysort 0 -1
1) "lisi"
2) "zhangsan"
3) "wangwu"
redis 127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "lisi"
2) "50"
3) "zhangsan"
4) "60"
5) "wangwu"
6) "80"
🛠️ Key设计黄金法则
Redis 没有类似 MySQL 的表结构,如何区分不同类型的键呢?
例如,需要存储用户、商品信息到redis,有一个用户id是1,有一个商品id恰好也是1
key的结构
Redis 键支持层级结构,多个单词用 : 隔开,格式如下:
项目名:业务名:子业务:id
这个格式并非固定,也可以根据自己的需求来删除或添加词条。例如我们的项目名称叫 heima,有user和product两种不同类型的数据,我们可以这样定义key:
- user相关的key:heima:user:1
- product相关的key:heima:product:1
- 用户系统:user:baseinfo:1001
- 商品缓存:product:detail:2023
- 秒杀库存:seckill:stock:20230915
❗ 避坑指南
- 禁用KEYS*:用SCAN命令替代防止阻塞
- 内存监控:定期使用INFO memory查看使用量
- 管道优化:批量命令使用pipeline减少网络开销
- 持久化配置:生产环境建议RDB+AOF双保险