完整详细的Redis学习笔记
Posted 遇事不决问清风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完整详细的Redis学习笔记相关的知识,希望对你有一定的参考价值。
学习参考视频:【狂神说Java】Redis
Redis
一、redis相关概述
redis属于非关系型数据库。
1.关于非关系型数据库的介绍
非关系型的数据库,也就是NoSQL(Not Only SQL)。
关系型数据库:列+行,同一个表下数据的结构是一样的。
非关系型数据库:数据存储没有固定的格式,并且可以进行横向扩展。
NoSQL泛指非关系型数据库,随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区,暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的。
NoSQL的特点
- 方便扩展(数据之间没有关系,很好扩展!)
- 大数据量高性能(Redis一秒可以写8万次,读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
- 数据类型是多样型的!(不需要事先设计数据库,随取随用)
NoSQL的分类
类型 | 部分代表 | 特点 |
---|---|---|
列存储 | Hbase Cassandra HypertableHypertable | 顾名思义,是按列存储数据的。 最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。 |
文档存储 | MongoDB CouchDB | 文档存储一般用类似json的格式存储,存储的内容是文档型的。 这样也就有有机会对某些字段建立索引,实现关系数据库的某些功能。 |
key-value存储 | Tokyo Cabinet/Tyrant Berkeley DB MemcacheDB Redis | 可以通过key快速查询到其value。 一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能) |
图存储 | Neo4J FlockDB | 图形关系的最佳存储。 使用传统关系数据库来解决的话性能低下,而且设计使用不方便。 |
对象存储 | db4o Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。 |
xml数据库 | Berkeley DB XML BaseX | 高效的存储XML数据,并支持XML的内部查询语法, |
2.什么是redis
Redis是一款内存高速缓存数据库。Redis全称为:Remote Dictionary Server (远程数据服务),使用C语言编写,Redis是一个key-value存储系统(键值存储系统),支持丰富的数据类型,如:String、list、set、zset、hash。
3.redis的应用场景
众多语言都支持Redis,因为Redis交换数据快,在服务器中常用来存储一些需要频繁调取的数据,节省内存开销,也极大的提升了速度。
将一些热点数据存储到Redis中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。
1、会话缓存(最常用)
2、消息队列(支付)
3、活动排行榜或计数
4、发布,订阅消息(消息通知)
5、商品列表,评论列表
二、五大数据类型
在介绍五大数据类型之前,我们先来了解一下关于key操作的基础命令
命令 | 说明 |
---|---|
keys * | 查看当前数据库所有的key |
exists | 判断指定key是否存在 |
del | 删除指定key |
expire | 设置key的过期时间 |
type | 查看key的类型 |
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> type name
string
127.0.0.1:6379> expire name 10 #设置10s到期时间
(integer) 1
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists name #10s后过期了
(integer) 0
127.0.0.1:6379> keys * #在查看当前数据库所有的key,发现无了
(empty list or set)
String(字符串)
由于redis输入命令后面会有提示,我这里就写他的关键词了
命令 | 描述 |
---|---|
APPEND | 向指定的key的value后追加字符串 |
DECR/INCR | 将指定key的value数值进行+1/-1(仅对于数字) |
INCRBY/DECRBY | 按指定的步长对数值进行加减 |
INCRBYFLOAT | 为数值加上浮点型数值 |
STRLEN | 获取key保存值的字符串长度 |
GETRANGE | 按起止位置获取字符串(闭区间,起止位置都取) |
SETRANGE | 用指定的value 替换key中 offset开始的值 |
GETSET | 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 |
SETNX | 仅当key不存在时进行set |
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"thenie"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> append name Shuai #向指定字符串后加Shuai
(integer) 11
127.0.0.1:6379> get name
"thenieShuai"
127.0.0.1:6379> DECR age #自减
(integer) 17
127.0.0.1:6379> INCR age #自增
(integer) 18
127.0.0.1:6379> DECRBY age 5 #指定减少
(integer) 13
127.0.0.1:6379> INCRBY age 5
(integer) 18
127.0.0.1:6379> STRLEN age #返回字符串长度
(integer) 2
127.0.0.1:6379> getrange name 0 -1 #返回完整字符串
"thenieShuai"
127.0.0.1:6379> getrange name 0 6 #返回下标为0~6的字符串
"thenieS"
127.0.0.1:6379> setrange name 6 Haokan #从6的位置开始用Haokan进行覆盖
(integer) 12
127.0.0.1:6379> get name
"thenieHaokan"
127.0.0.1:6379> GETSET name kuaijieshule #返回name的值,并进行指定的修改
"thenieHaokan"
127.0.0.1:6379> GET name
"kuaijieshule"
127.0.0.1:6379> setnx name , #创建,失败,因为存在key为name
(integer) 0
127.0.0.1:6379> get name
"kuaijieshule"
String类似的使用场景:value除了是字符串还可以是数字,用途举例:
- 计数器
- 统计多单位的数量:uid:123666:follow 0
- 粉丝数
- 对象存储缓存
Hash(哈希)
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
命令 | 描述 |
---|---|
HSET | 将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0 |
HMSET | 同时将多个 field-value (域-值)对设置到哈希表 key 中。 |
HSETNX | 只有在字段 field 不存在时,设置哈希表字段的值。 |
HEXISTS | 查看哈希表 key 中,指定的字段是否存在。 |
HGET | 获取存储在哈希表中指定字段的值 |
HMGET | 获取所有给定字段的值 |
HGETALL | 获取在哈希表key 的所有字段和值 |
HKEYS | 获取哈希表key中所有的字段 |
HLEN | 获取哈希表中字段的数量 |
HVALS | 获取哈希表中所有值 |
HDEL | 删除哈希表key中一个/多个field字段 |
HINCRBY | 为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段 |
HINCRBYFLOAT | 为哈希表 key 中的指定字段的浮点数值加上增量 n。 |
127.0.0.1:6379> HSET mymap k1 v1 #初始化一个key为mymap的集合
(integer) 1
127.0.0.1:6379> HSET mymap k2 v2
(integer) 1
127.0.0.1:6379> HMSET mymap k3 v3 k4 v4
OK
127.0.0.1:6379> HEXISTS mymap k1 #判断k1在mymap中是否存在
(integer) 1
127.0.0.1:6379> HEXISTS mymap k5
(integer) 0
127.0.0.1:6379> HGETALL mymap #返回mymap中所有的key和value
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"
7) "k4"
8) "v4"
127.0.0.1:6379> HGET mymap k1
"v1"
127.0.0.1:6379> HKEYS mymap #返回mymap中所有的key
1) "k1"
2) "k2"
3) "k3"
4) "k4"
127.0.0.1:6379> HVALS mymap
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> HDEL mymap k2 #删除mymap中的k2
(integer) 1
127.0.0.1:6379> HKEYS mymap
1) "k1"
2) "k3"
3) "k4"
127.0.0.1:6379> HSET mymap number 10
(integer) 1
127.0.0.1:6379> hget mymap number
"10"
127.0.0.1:6379> HINCRBY mymap number 10
(integer) 20
Hash变更的数据user name age,尤其是用户信息之类的,经常变动的信息!Hash更适合于对象的存储,Sring更加适合字符串存储!
List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
首先我们列表,可以经过规则定义将其变为队列、栈、双端队列等
正如图Redis中List是可以进行双端操作的,所以命令也就分为了LXXX和RLLL两类,有时候L也表示List例如LLEN
命令 | 描述 |
---|---|
LPUSH/RPUSH | 从左边/右边向列表中PUSH值(一个或者多个)。 |
LRANGE | 获取list 起止元素==(索引从左往右 递增)== |
LPUSHX/RPUSHX | 向已存在的列名中push值(一个或者多个) |
LINSERT key BEFORE|AFTER pivot value | 在指定列表元素的前/后 插入value |
LLEN | 查看列表长度 |
LINDEX | 通过索引获取列表元素 |
LSET | 通过索引为元素设值 |
LPOP/RPOP | 从最左边/最右边移除值 并返回 |
RPOPLPUSH source destination | 将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部 |
LTRIM | 通过下标截取指定范围内的列表 |
LREM key count value | List中是允许value重复的 count > 0 :从头部开始搜索 然后删除指定的value 至多删除count个 count < 0 :从尾部开始搜索… count = 0 :删除列表中所有的指定value。 |
BLPOP/BRPOP | 移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
127.0.0.1:6379> rpush list a b c d e f #初始化key为list的列表
(integer) 6
127.0.0.1:6379> LRANGE list 0 -1 #从左至右返回list
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379> LPUSH list 1 #向左插入1
(integer) 7
127.0.0.1:6379> LRANGE list 0 -1
1) "1"
2) "a"
3) "b"
4) "c"
5) "d"
6) "e"
7) "f"
127.0.0.1:6379> RPUSH list 2 #向右插入2
(integer) 8
127.0.0.1:6379> LRANGE list 0 -1 #从左至右返回list
1) "1"
2) "a"
3) "b"
4) "c"
5) "d"
6) "e"
7) "f"
8) "2"
127.0.0.1:6379> llen list
(integer) 8
127.0.0.1:6379> LINDEX list 2
"b"
127.0.0.1:6379> LPUSH list1 1 #初始化一个list1的列表
(integer) 1
127.0.0.1:6379> RPOPLPUSH list list1 #从list的右边弹出一个值并向list的左边插入
"2"
127.0.0.1:6379> LRANGE list1 0 -1
1) "2"
2) "1"
127.0.0.1:6379> LPOP list1
"2"
127.0.0.1:6379> LPOP list1
"1"
127.0.0.1:6379> LTRIM list 1 8
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
小结
- list实际上是一个链表,before Node after , left, right 都可以插入值
- 如果key不存在,则创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或者改动值,效率最高!修改中间元素,效率相对较低
应用:
消息排队!消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(集合)
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令 | 描述 |
---|---|
SADD | 向集合中无序增加一个/多个成员 |
SCARD | 获取集合的成员数 |
SMEMBERS | 返回集合中所有的成员 |
SISMEMBER | 查询member元素是否是集合的成员,结果是无序的 |
SRANDMEMBER | 随机返回集合中count个成员,count缺省值为1 |
SPOP | 随机移除并返回集合中count个成员,count缺省值为1 |
SMOVE source destination member | 将source集合的成员member移动到destination集合 |
SREM | 移除集合中一个/多个成员 |
SDIFF | 返回所有集合的差集 key1- key2 - … |
SDIFFSTORE destination key1[key2..] | 在SDIFF的基础上,将结果保存到集合中==(覆盖)==。不能保存到其他类型key噢! |
SINTER key1 [key2..] | 返回所有集合的交集 |
SINTERSTORE destination key1[key2..] | 在SINTER的基础上,存储结果到集合中。覆盖 |
SUNION key1 [key2..] | 返回所有集合的并集 |
SUNIONSTORE destination key1 [key2..] | 在SUNION的基础上,存储结果到及和张。覆盖 |
SSCAN KEY [MATCH pattern] [COUNT count] | 在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分 |
127.0.0.1:6379> sadd set a b c #初始化key为set的集合
(integer) 3
127.0.0.1:6379> sadd set1 d e f #初始化key为set1的集合
(integer) 3
127.0.0.1:6379> SMEMBERS set #查看指定集合的全部成员
1) "b"
2) "c"
3) "a"
127.0.0.1:6379> SISMEMBER set b #判断b是否存在于集合中
(integer) 1
127.0.0.1:6379> SISMEMBER set c
(integer) 1
127.0.0.1:6379> SISMEMBER set e
(integer) 0
127.0.0.1:6379> SRANDMEMBER set 2 #随机返回两个成员
1) "b"
2) "c"
127.0.0.1:6379> SRANDMEMBER set 2
1) "a"
2) "c"
127.0.0.1:6379> SADD set d
(integer) 1
127.0.0.1:6379> SMOVE set set1 a #将set中的a移入set1中
(integer) 1
127.0.0.1:6379> SMEMBERS set
1) "b"
2) "c"
3) "d"
127.0.0.1:6379> SMEMBERS set1
1) "a"
2) "f"
3) "e"
4) "d"
127.0.0.1:6379> SREM set1 a #删除set1中的a元素
(integer) 1
127.0.0.1:6379> SMEMBERS set1
1) "f"
2) "e"
3) "d"
ZSet(sorted set 有序集合)
不同的是每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大的排序。
score相同:按字典顺序排序
有序集合的成员是唯一的,但分数(score)却可以重复。
命令 | 描述 |
---|---|
ZADD key score member1 [score2 member2] | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZCARD key | 获取有序集合的成员数 |
ZCOUNT key min max | 计算在有序集合中指定区间score的成员数 |
ZINCRBY key n member | 有序集合中对指定成员的分数加上增量 n |
ZSCORE key member | 返回有序集中,成员的分数值 |
ZRANK key member | 返回有序集合中指定成员的索引 |
ZRANGE key start end | 通过索引区间返回有序集合成指定区间内的成员 |
ZRANGEBYLEX key min max | 通过字典区间返回有序集合的成员 |
ZRANGEBYSCORE key min max | 通过分数返回有序集合指定区间内的成员==-inf 和 +inf分别表示最小最大值,只支持开区间()== |
ZLEXCOUNT key min max | 在有序集合中计算指定字典区间内成员数量 |
ZREM key member1 [member2..] | 移除有序集合中一个/多个成员 |
ZREMRANGEBYLEX key min max | 移除有序集合中给定的字典区间的所有成员 |
ZREMRANGEBYRANK key start stop | 移除有序集合中给定的排名区间的所有成员 |
ZREMRANGEBYSCORE key min max | 移除有序集合中给定的分数区间的所有成员 |
ZREVRANGE key start end | 返回有序集中指定区间内的成员,通过索引,分数从高到底 |
ZREVRANGEBYSCORRE key max min | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
ZREVRANGEBYLEX key max min | 返回有序集中指定字典区间内的成员,按字典顺序倒序 |
ZREVRANK key member | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
ZINTERSTORE destination numkeys key1 [key2 ..] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中,numkeys:表示参与运算的集合数,将score相加作为结果的score |
ZUNIONSTORE destination numkeys key1 [key2..] | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
ZSCAN key cursor [MATCH pattern\\] [COUNT count] | 迭代有序集合中的元素(包括元素成员和元素分值) |
-------------------ZADD--ZCARD--ZCOUNT--------------
127.0.0.1:6379> ZADD myzset 1 m1 2 m2 3 m3 # 向有序集合myzset中添加成员m1 score=1 以及成员m2 score=2..
(integer) 2
127.0.0.1:6379> ZCARD myzset # 获取有序集合的成员数
(integer) 2
127.0.0.1:6379> ZCOUNT myzset 0 1 # 获取score在 [0,1]区间的成员数量
(integer) 1
127.0.0.1:6379> ZCOUNT myzset 0 2
(integer) 2
----------------ZINCRBY--ZSCORE--------------------------
127.0.0.1:6379> ZINCRBY myzset 5 m2 # 将成员m2的score +5
"7"
127.0.0.1:6379> ZSCORE myzset m1 # 获取成员m1的score
"1"
127.0.0.1:6379> ZSCORE myzset m2
"7"
--------------ZRANK--ZRANGE-----------------------------------
127.0.0.1:6379> ZRANK myzset m1 # 获取成员m1的索引,索引按照score排序,score相同索引值按字典顺序顺序增加
(integer) 0
127.0.0.1:6379> ZRANK myzset m2
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 1 # 获取索引在 0~1的成员
1) "m1"
2) "m3"
127.0.0.1:6379> ZRANGE myzset 0 -1 # 获取全部成员
1) "m1"
2) "m3"
3) "m2"
#testset=>abc,add,amaze,apple,back,java,redis score均为0
------------------ZRANGEBYLEX---------------------------------
127.0.0.1:6379> ZRANGEBYLEX testset - + # 返回所有成员
1) "abc"
2) "add"
3) "amaze"
4) "apple"
5) "back"
6) "java"
7) "redis"
127.0.0.1:6379> ZRANGEBYLEX testset - + LIMIT 0 3 # 分页 按索引显示查询结果的 0,1,2条记录
1) "abc"
2) "add"
3) "amaze"
127.0.0.1:6379> ZRANGEBYLEX testset - + LIMIT 3 3 # 显示 3,4,5条记录
1) "apple"
2) "back"
3) "java"
127.0.0.1:6379> ZRANGEBYLEX testset (- [apple # 显示 (-,apple] 区间内的成员
1) "abc"
2) "add"
3) "amaze"
4) "apple"
127.0.0.1:6379> ZRANGEBYLEX testset [apple [java # 显示 [apple,java]字典区间的成员
1) "apple"
2) "back"
3) "java"
-----------------------ZRANGEBYSCORE---------------------
127.0.0.1:6379> ZRANGEBYSCORE myzset 1 10 # 返回score在 [1,10]之间的的成员
1) "m1"
2) "m3"
3) "m2"
127.0.0.1:6379> ZRANGEBYSCORE myzset 1 5
1) "m1"
2) "m3"
--------------------ZLEXCOUNT-----------------------------
127.0.0.1:6379> ZLEXCOUNT testset - +
(integer) 7
127.0.0.1:6379> ZLEXCOUNT testset [apple [java
(integer) 3
------------------ZREM--ZREMRANGEBYLEX--ZREMRANGBYRANK--ZREMRANGEBYSCORE--------------------------------
127.0.0.1:6379> ZREM testset abc # 移除成员abc
(integer) 1
127.0.0.1:6379> ZREMRANGEBYLEX testset [apple [java # 移除字典区间[apple,java]中的所有成员
(integer) 3
127.0.0.1:6379> ZREMRANGEBYRANK testset 0 1 # 移除排名0~1的所有成员
(integer) 2
127.0.0.1:6379> ZREMRANGEBYSCORE myzset 0 3 # 移除score在 [0,3]的成员
(integer) 2
# testset=> abc,add,apple,amaze,back,java,redis score均为0
# myzset=> (m1,1),(m2,2),(m3,3),(m4,4),(m7,7),(m9,9)
----------------ZREVRANGE--ZREVRANGEBYSCORE--ZREVRANGEBYLEX-----------
127.0.0.1:6379> ZREVRANGE myzset 0 3 # 按score递减排序,然后按索引,返回结果的 0~3
1) "m9"
2) "m7"
3) "m4"
4) "m3"
127.0.0.1:6379> ZREVRANGE myzset 2 4 # 返回排序结果的 索引的2~4
1) "m4"
2) "m3"
3) "m2"
127.0.0.1:6379> ZREVRANGEBYSCORE myzset 6 2 # 按score递减顺序 返回集合中分数在[2,6]之间的成员
1) "m4"
2) "m3"
3) "m2"
127.0.0.1:6379> ZREVRANGEBYLEX testset [java (add # 按字典倒序 返回集合中(add,java]字典区间的成员
1) "java"
2) "back"
3) "apple"
4) "amaze"
-------------------------ZREVRANK------------------------------
127.0.0.1:6379> ZREVRANK myzset m7 # 按score递减顺序,返回成员m7索引
(integer) 1
127.0.0.1:6379> ZREVRANK myzset m2
(integer) 4
# mathscore=>(xm,90),(xh,95),(xg,87) 小明、小红、小刚的数学成绩
# enscore=>(xm,70),(xh,93),(xg,90) 小明、小红、小刚的英语成绩
-------------------ZINTERSTORE--ZUNIONSTORE-----------------------------------
127.0.0.1:6379> ZINTERSTORE sumscore 2 mathscore enscore # 将mathscore enscore进行合并 结果存放到sumscore
(integer) 3
127.0.0.1:6379> ZRANGE sumscore 0 -1 withscores # 合并后的score是之前集合中所有score的和
1) "xm"
2) "160"
3) "xg"
4) "177"
5) "xh"
6) "188"
127.0.0.1:6379> ZUNIONSTORE lowestscore 2 mathscore enscore AGGREGATE MIN # 取两个集合的成员score最小值作为结果的
(integer) 3
127.0.0.1:6379> ZRANGE lowestscore 0 -1 withscores
1) "xm"
2) "70"
3) "xg"
4) "87"
5) "xh"
6) "93"
应用案例:
- set排序 存储班级成绩表 工资表排序!
- 普通消息,1.重要消息 2.带权重进行判断
- 排行榜应用实现,取Top N测试
三、事务
Redis的单条命令是保证原子性的,而Redis事务不保证原子性。
1.如何使用事务
-
开启事务(
multi
) -
命令入队
-
执行事务(
exec
)开启事务后的命令不会立即执行,而是
exec
输入后一起执行127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> MULTI Redis学习笔记5:JedisRedisTemplate