什么是redis数据库
- Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。
- ,Redis 还支持 事务 、持久化、Lua 脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布/订阅模式,内存淘汰机制、过期删除机制
- Redis 应用非常广泛,如 Twitter、暴雪娱乐、Github、Stack Overflow、腾讯、阿里巴巴、京东、华为、新浪微博等,很多 中小型公司也在使用;
应用
- 记录朋友圈点赞数、评论数和点击数(hash)
- 记录朋友圈说说列表(排序),便于快速显示朋友圈(list)
- 记录文章的标题、摘要、作者和封面,用于列表页展示(hash)
- 记录朋友圈的点赞用户ID列表(list),评论ID列表(list),用 于显示和去重计数(zset)
- 缓存热点数据,减少数据库压力(hash)
- 如果朋友圈说说 ID 是整数 id,可使用 redis 来分配朋友圈说说 id(计数器)(string)
- 通过集合(set)的交并差集运算来实现记录好友关系(set) 游戏业务中,每局战绩存储(list)
Redis存储的结构
Redis 内部整体的存储结构是一个大的 HashMap,通过 key -value 的方式来存储组织数据的,key冲突通过 链表去实现,每个dictEntry为一个key/value对象,value为RedisObject。
所有的key值都是string类型。
key值的命名规范:
【推荐】Redis key命名需具有可读性以及可管理性,不该使用含义不清的key以及特别长的key名;
【强制】以英文字母开头,命名中只能出现 小写字母、数字、英文点号(.) 和 英文半角冒号(:);
【强制】不要 包含 特殊字符,如下划线、空格、换行、单双引号以及其他转义字符;
【强制】命名规范:业务模块名:业务逻辑含义:其他:value类型
例如:user:basic.info:{userid}:string
Redis中的value数据结构的类型?
Redis提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。
- string 是一个安全的二进制字符串;
- 双端队列 (链表)list:有序(插入有序);
- 散列表 hash:对顺序不关注,field 是唯一的;
- 无序集合 set:对顺序不关注,里面的值都是唯一的;
- 有序集合 zset:对顺序是关注的,里面的值是唯一的;根据 member 来确定唯一;根据 score 来确定有序;
String
String是一种安全字符串。
什么安全字符串?
使用安全字符串的函数都不会是超出字符串缓冲区。
常用指令
//设置 key-value 类型的值
127.0.0.1:6379> set name sjp
OK
# 根据 key 获得对应的 value
127.0.0.1:6379> get name
"sjp"
# 判断某个 key 是否存在
127.0.0.1:6379> exists name
(integer) 1
# 返回 key 所储存的字符串值的长度
127.0.0.1:6379> strlen name
(integer) 3
# 删除某个 key 对应的值
127.0.0.1:6379> del name
(integer) 1#批量设置 key-value类型的值
127.0.0.1:6379> mset name:1001 sjp name:1002 lisi
OK
# 批量获取多个 key 对应的 value
127.0.0.1:6379> mget name:1001 name:1002
1) "sjp"
2) "lisi"
string的应用
直接缓存整个对象的 JSON
命令例子:
SET user:1 '{"name":"sjp", "age":18}'。
采用将 key 进行分离为 user:ID:属性,采用 MSET 存储,用 MGET 获取各属性值,命令例子:
MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
计数器(字符串的内容为整数的时候可以使用)
# 设置 key-value 类型的值
127.0.0.1:6379> set count 1
OK
# 将 key 中储存的数字值增一
127.0.0.1:6379> incr count
(integer) 2
# 将key中存储的数字值加 10
127.0.0.1:6379> incrby count 100
(integer) 102
# 将 key 中储存的数字值减一
127.0.0.1:6379> decr count
(integer) 101
# 将key中存储的数字值键 10
127.0.0.1:6379> decrby count 10
(integer) 91
List
List 列表是双向链表实现,列表首尾操作(删除和增加)时间复杂度 O(1);.查找中间元素时间复杂度为O(n);
列表中数据是否压缩的依据:
1. 元素长度小于 48,不压缩;
2. 元素压缩前后长度差不超过 8,不压缩;
基础命令:
# 从队列的左侧入队一个或多个元素
LPUSH key value [value ...]
# 从队列的左侧弹出一个元素
LPOP key
# 从队列的右侧入队一个或多个元素
RPUSH key value [value ...]
# 从队列的右侧弹出一个元素
RPOP key
# 返回从队列的 start 和 end 之间的元素 0, 1 2 负索引
LRANGE key start end
# 从存于 key 的列表里移除前 count 次出现的值为 value 的
元素
# list 没有去重功能 hash set zset
LREM key count value
# 它是 RPOP 的阻塞版本,因为这个命令会在给定list无法弹出
任何元素的时候阻塞连接
BRPOP key timeout # 超时时间 + 延时队列
应用场景
栈
LPUSH + LPOP
# 或者
RPUSH + RPOP
队列
LPUSH + RPOP
# 或者
RPUSH + LPOP
消息队列
消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息 和 保证消息可靠性。
- 生产者使用lpush往list集合中添加消息
- 消费者使用 brpop往list集合中获取消息
BRPOP命令也称为 阻塞式读取,客户端在 没有 读到队列数据时,自动阻塞,直到有新的数据写入队列,再开始读取新数据
2、消息队列如何处理重复的消息?
消费者要实现重复消息的判断,需要 2 个方面的要求:
- 每个消息都有一个全局的 ID。
- 消费者 要记录已经处理过的消息的 ID。当收到一条消息后,消费者程序就可以对比收到的消息 ID 和记录的已处理过的消息 ID,来判断当前收到的消息有没有经过处理。如果已经处理过,那么,消费者程序就不再进行处理了。
List 并不会为每个消息生成 ID 号,所以我们需要自行为每个消息生成一个全局唯一ID,生成之后,我们在用 LPUSH 命令把消息插入 List 时,需要在消息中包含这个全局唯一 ID
3.消息队列如何保证消息的可靠性?
当消费者程序从 List 中读取一条消息后,List 就不会再留存这条消息了。所以,如果消费者程序在处理消息的过程出现了故障或宕机,就会导致消息没有处理完成,那么,消费者程序再次启动后,就没法再次从 List 中读取消息了。
,List 类型提供了 BRPOPLPUSH
命令,这个命令的 作用是让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存。
Hash
Hash 是一个键值对(key - value)集合,其中 value 的形式如: value=[{field1,value1},...{fieldN,valueN}]
。Hash 特别适合用于存储对象.
内部实现
Hash 类型的底层数据结构是由压缩列表或哈希表实现的:
如果 哈希类型元素个数小于 512
个(默认值,可由 hash-max-ziplist-entries
配置),所有值小于 64
字节(默认值,可由 hash-max-ziplist-value
配置)的话,Redis 会使用压缩列表作为 Hash 类型的底层数据结构。
基础命令
# 获取 key 对应 hash 中的 field 对应的值
HGET key field
# 设置 key 对应 hash 中的 field 对应的值
HSET key field value
# 设置多个hash键值对
HMSET key field1 value1 field2 value2 ... fieldn
valuen
# 获取多个field的值
HMGET key field1 field2 ... fieldn
# 给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
# 获取 key 对应的 hash 有多少个键值对
HLEN key
# 删除 key 对应的 hash 的键值对,该键为field
HDEL key field
应用
一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储。
购物车
set
集合
Set 类型是一个 无序并唯一的键值集合,它的 存储顺序不会按照插入的先后顺序进行存储
一个集合最多可以存储 2^32-1
个元素。概念和数学中个的集合基本类似,可以交集,并集,差集等等。。
存储结构
元素都为 整数且节点数量小于等于 512(set-max-intsetentries),则使用整数数组存储;
元素当中有一个不是整数或者节点数量大于 512,则使用 字典存储;
基础命令
# 添加一个或多个指定的member元素到集合的 key中
SADD key member [member ...]
# 计算集合元素个数
SCARD key
# SMEMBERS key
SMEMBERS key
# 返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member
# 随机返回key集合中的一个或者多个元素,不删除这些元素
SRANDMEMBER key [count]
# 从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]
# 返回一个集合与给定集合的差集的元素SDIFF key [key ...]
# 返回指定所有的集合的成员的交集
SINTER key [key ...]
# 返回给定的多个集合的并集中的所有成员
SUNION key [key ...]
set与list的区别
list可以存储重复元素,set只能存储非重复元素。
list是按照元素的插入的先后顺序进行存储,而set则是无序方式存储元素
应用
点赞
set可以保证一个用户只能点一个赞,例如,key是文章id,value是用户id
uid:1
、uid:2
、uid:3
三个用户分别对 article:1 文章点赞了。
#uid:1 uid:2 uid:3 用户对文章 article:1 点赞
127.0.0.1:6379> sadd article:1 uid:1
(integer) 1
127.0.0.1:6379> sadd article:1 uid:2
(integer) 1
127.0.0.1:6379> sadd article:1 uid:3
(integer) 1#获取 article:1 文章所有点赞用户 :
127.0.0.1:6379> smembers article:1
1) "uid:3"
2) "uid:2"
3) "uid:1"#获取 article:1 文章的点赞用户数量:
127.0.0.1:6379> scard article:1
(integer) 3
推荐好友
Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等。
key 可以是用户id,value 则是好友
#插入A的好友
127.0.0.1:6379> sadd follow:A sjp king lisi
(integer) 3
#插入B的好友
127.0.0.1:6379> sadd follow:B chen lisi sjp
(integer) 3
#A不同于B的好友
127.0.0.1:6379> sdiff follow:A follow:B
1) "king"
#A与B的共同好友
127.0.0.1:6379> sinter follow:A follow:B
1) "sjp"
2) "lisi"
抽奖
key为抽奖活动名,value为员工名称,把所有员工名称放入抽奖箱
#添加抽奖人员
127.0.0.1:6379> sadd lucky A B C D E
(integer) 5#允许重复抽奖
127.0.0.1:6379> srandmember lucky 1
1) "C"
127.0.0.1:6379> srandmember lucky 2
1) "E"
2) "D"
127.0.0.1:6379> srandmember lucky 3
1) "B"
2) "C"
3) "A"#不重复抽奖
127.0.0.1:6379> spop lucky 1
1) "A"
127.0.0.1:6379> spop lucky 2
1) "D"
2) "E"
zset
Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合
有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。 zset 根据分值进行排序。
基础命令:
# 添加到键为key有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score
member ...]
# 从键为key有序集合中删除 member 的键值对
ZREM key member [member ...]
# 返回有序集key中,成员member的score值
ZSCORE key member
# 为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
# 返回key的有序集元素个数
ZCARD key
# 返回有序集key中成员member的排名
ZRANK key member
# 返回存储在有序集合key中的指定范围的元素 order by id
limit 1,100
ZRANGE key start stop [WITHSCORES]
# 返回有序集key中,指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]
应用场景
有序集合比较典型的使用场景就是排行榜。例如 学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等。