Redis基础1:https://developer.aliyun.com/article/1521821
set数据类型
SET类型:用于保存多个字符串类型的元素(集合类型),但是要求存储的元素不能重复(唯一性),并且存储的元素是无序的(与list数据类型对应)
SADD:将一个或者多个元素添加到set中(重复的元素无法添加)
语法格式:SADD key member [member…]
时间复杂度:O(1)
返回值:成功添加的元素的个数
SMEMBERS:获取Set中的所有元素,但是元素间的顺序是无序的
语法格式:SMEMBERS key
时间复杂度:O(1)
返回值:set中的所有元素或者nil
SISMEMBER:判断元素是否在set中
语法格式:SISMEMBER key member
时间复杂度:O(1)
返回值:1表示存在,0表示不存在
SPOP:随机删除set中的元素
语法格式:SPOP key count (count可省略,表示删除元素的个数)
时间复杂度:O(1)
返回值:成功删除的元素个数
SMOVE:从元素从一个set移动到另一个set中
语法格式:SMOVE source destination member (如果目标set中已存在要移动的元素,任然会成功移动只是没有实际效果)
时间复杂度:O(1)
返回值:1表示移动成功,0表示移动失败(如果要移动的元素在source中不存在,就会移动失败返回0)
SREM:删除set中的元素
语法格式:SREM key member [member …] (可以一次删除一个或多个元素)
时间复杂度:O(1)
返回值:成功删除的元素个数
集合间操作:交集、并集以及差集
SINTER:获取给定的set之间的交集
语法格式:SINTER key [key …]
时间复杂度:O(N*M) N是最小的集合的元素个数,M是最大的集合的元素个数
返回值:交集中的元素
SINTERSTORE: 将set之间的交集存储到 destination
语法格式:SINTERSTORE destination key [key …]
时间复杂度:O(N*M)
返回值:交集的元素个数
SUNION:获取给定的set之间的并集
语法格式:SUNION key [key …]
时间复杂度:O(N) N指的是总的元素个数(所有key的元素个数之和)
返回值:并集中的元素
SUNIONSTORE:将set之间的并集存储到 destination
语法格式:SUNIONSTORE key [key …]
时间复杂度:O(N)
返回值:并集中的元素个数
SDIFF:获取给定的set之间的差集(差集结果与key的顺序有关)
语法格式:SDIFF key [key …]
时间复杂度:O(N) N指的是总的元素个数
返回值:差集中的元素
SDIFFSTORE:将set之间的差集存储到distination中
语法格式:SDIFFSTORE destination key [key …]
时间复杂度:O(N*M)
返回值:差集中的元素个数
集合类型的内部编码:
Insert(整数集合):当元素个数小于set-max-intset-entries配置(默认512)时,Redis会使用intset来作为集合的内部实现从而节省内存
Hashtable(哈希表):当集合类型无法满足intset的条件时,Redis就会使用hashtable作为集合的内部实现
SET的应用场景:
- 保存用户的标签(“用户画像”,根据用户历史兴趣行为投其所好)
- 利用Set来计算用户的共同好友,并可以进行好友推荐(SET集合求交集相对比较容易)
- 使用Set进行UV(去重),UV指的是每个用户的访问量(访问不同页面的个数),PV是整体用户的浏览量
zset数据类型
ZSET:有序集合,存储的元素唯一且有序(升序或者降序)
使用
ZADD:向zset添加一组或多组元素和分数 分数可以被表示为小数,要求member是唯一的,分数可以相同,首先是按照分数进行排序,如果分数相同再按照元素的字典序排列
语法格式:ZADD key [NX | XX][GT|LT] [CH] [INCR] score member [score member …] (score和member可以相互查找)
LT:新的分数比之前的分数小就会更新
GT:新的分数比之前的分数大就会更新
CH:该参数会使返回值包含修改成功的元素个数
INCR:对于指定的元素加上指定的分数,但只能指定一个元素和分数,并且返回值变成修改后的分数值
时间复杂度:O(log N) N是集合元素的个数,由于ZSET是有序的结构,要求新增的元素要放到合适的位置
返回值:返回新增成功的元素个数,对元素修改后会重新进行排序
ZCRAD:获取一个zset的基数,即zset中的元素个数
语法格式:ZCARD key
时间复杂度:O(1)
返回值: zset中的元素个数
ZCOUNT: 返回分数在min和max之间的元素个数,在默认情况下是闭区间,可以通过(进行排除边界值
语法格式: ZCOUNT key min max (min和max支持浮点数,并且支持inf(无穷大)和 -inf(负无穷大))
时间复杂度:O(log N) zset内部会记录每个元素当前的次序,zcount命令使用时先找到min和max对应的元素(log N),然后根据次序求个数
返回值:满足条件的元素列表的个数
ZRANGE:查询有序集合中的元素详情
语法格式:ZRANGE key start stop [withscores] withscores可以使返回结果加上分数
时间复杂度:O(log N + M) log N是根据下标找位置,M是对start和stop之间进行遍历
返回值:区间内的元素列表
ZREVRANGE: 返回指定区间里的元素,分数按照降序排序
语法格式:ZRANGE key start stop [withscores] withscores可以使返回结果加上分数
时间复杂度:O(log N + M) log N是根据下标找位置,M是对start和stop之间进行遍历
返回值:区间内的元素列表
ZRANGEBYSCORE: 返回分数在min和max之间的元素
语法格式:ZRANGE key max min [withscores] withscores可以使返回结果加上分数
时间复杂度:O(log N + M) log N是根据下标找位置,M是对start和stop之间进行遍历
返回值:区间内的元素列表
ZPOPMAX:删除并返回分数最高的count的个数(相当于尾删)
语法格式:ZPOPMAX KEY [COUNT]
时间复杂度:O(log N * M) N是有序集合的元素个数,M是要删除的元素个数 (查找到特定位置再进行删除)
返回值: 分数和元素列表
BZPOPMAX:ZPOPMAX的阻塞版本
语法格式:BZPOPMAX key [key …] timeout
时间复杂度:O(log N) 删除最大值花费的时间
返回值:元素列表
ZPOPMIN:删除并返回分数最低的count个元素
语法格式:ZPOPMIN key [count]
时间复杂度:O(logN * M)
返回值:分数和元素列表
BZPOPMIN:ZPOPMIN的阻塞版本
语法格式:BZPOPMIN key [key …] timeout
时间复杂度:O(log N) 删除最大值花费的时间
返回值:元素列表
ZRANK:返回指定元素的排名,升序
语法格式:ZRANK key member
时间复杂度:O(log N) 查询位置
返回值:排名(即元素的下标,)
ZREVRANK:返回指定元素的排名,降序
语法格式:ZREVRANK key member
时间复杂度:O(log N) 查询位置
返回值:排名(即元素的下标)
ZSCORE:返回指定元素的分数
语法格式:ZSCORE key member
时间复杂度:O(1)
返回值:分数
ZREM:删除指定的元素
语法格式:ZREM key member [member …]
时间复杂度:O(M * logN)
返回值:删除成功的元素个数
ZREMRANGEBYRANK: 删除指定范围的元素(按照排序)
语法格式:ZRENRANGEBYRANK key start stop
时间复杂度:O(logN + M) M指的是区间内的元素个数,N指的是集合内的元素个数
返回值:删除成功的元素个数
ZREMRANGEBYSCORE: 按照分数删除指定范围的元素
语法格式:ZREMRANGEBYSCORE key min max
时间复杂度:O(logN + M)
返回值:删除成功的元素个数
ZINCYBY:为指定的元素关联的分数添加指定的分数值 ,操作后集合会保持有序
语法格式:ZINCRBY key increment member
时间复杂度:O(log N)
返回值:增加后的元素的分数
ZINTESTORE:将交集结果保存到另一个destination中
语法格式:ZINTERSTORE destination numbers key [key …] [WEIGHTS weight][weight …] [AGGREAGATE <SUM | MIN |MAX>]
Numbers: 描述后面有几个key参与运算,避免选项和keys混淆
Weights:权重,此处的权重相当于一个系数,会乘以当前的分数
Aggregate:当member相同score不同时,分数的计算规则<SUM | MIN |MAX>,默认规则时SUM(加和)
时间复杂度:O(M*log M)
返回值:destination中的元素个数
ZUNIONSTORE:将并集结果保存到另一个destination中
语法格式:ZUNIONSTORE destination numbers key [key …] [WEIGHTS weight][weight …] [AGGREAGATE <SUM | MIN |MAX>
时间复杂度:O(M*log M) + O(N)
返回值:destination中的元素个数
Zset的内部编码方式:如果有序集合内部的元素个数较少或者单个元素体积较小时使用ziplist进行存储,如果当前元素个数较多或者单个元素体积较大时使用skiplist进行存储
应用场景:
排行榜系统(热搜榜、游戏天梯排行)(关键要点:排行“分数”是实时变化的,能够高效实现更新排行)
其他数据类型
Stream数据类型:是一个阻塞队列,作为消息队列的一个重要支撑,属于是List中的blpop和brpop的升级版本
Geospatial数据类型:用来存储坐标(经纬度),存储一些点之后就可以让用户给定一个坐标,去从刚才存储的点进行查找(按照半径或矩形区域等),常用于地图中
HyperLogLog数据类型:估算集合中的元素个数
Bitmap(位图)数据类型:位运算
Bitfields(位域)数据类型:可以简单理解为字节数组,然后把这个字节数组中的某几个位赋予特殊的含义,并可以进行读取、修改以及算数等运算,可以节省空间
渐进式遍历:每执行一次命令,只获取到其中一小部分,要想得到所有的key,就需要多次执行渐进式命令(“化整为零”),遍历过程中随时都可以终止,不会对服务器产生任何副作用
代表命令SCAN:
语法格式:SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
Cursor: 光标指向当前遍历的位置,从0开始但是并不代表下标
Match:匹配模式
Count:限制一次命令匹配得到的元素个数,只是一个“提示\建议”,并不是精确的数值,不用每次设置成相同的数字
Type:指定遍历value的类型
数据库管理命令:Redis中的数据库是现成的,作为用户不能创建新的数据库,也不能删除已有的数据库。
默认Redis提供了16个数据库(0~15),这16个数据库中的数据是隔离的,默认使用的数据库是0号
Select index (index指的是数据库编号):切换数据库
Dbsize:获取到当前数据库中key的个数
Flushdb:删除当前数据库中所有的key
Flushall:删除所有数据库中所有的key
四、maven项目中使用Redis
在maven项目中使用的是Jedis来操作redis
首先从maven中央仓库中引入jedis依赖:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.4.3</version> </dependency>
在连接云服务器时实现本地端口的SSH端口映射,提高本地访问Redis的安全性;
使用代码来操作Redis:
Redis的各种命令都可以通过Jedis的方法来实现:jedis官方文档
五、SpringBoot项目中使用Redis
在创建SpringBoot项目在NoSQL中勾选redis依赖:
在配置文件中添加redis的地址和端口号:
spring: redis: host: 127.0.0.1 port: xxxx
在Spring中使用RedisTemplate来操作Redis,相比jedis不能直接操作,而是需要选择相应的数据类型再进行操作:
例如操作字符串类型:
@Autowired private RedisTemplate redisTemplate; @Test void testString() { // 设置数据 redisTemplate.opsForValue().set("key1","张三"); redisTemplate.opsForValue().set("key2","lucy"); // 测试数据 Assertions.assertEquals("张三",redisTemplate.opsForValue().get("key1")); Assertions.assertEquals("lucy",redisTemplate.opsForValue().get("key2")); }
想要执行Redis的一些原生命令,就需要使用RedisTemplate中的execute方法,使用lamda表达式来实现,以flushall命令为例:
// 清空数据库 redisTemplate.execute((RedisConnection connection) ->{ connection.flushAll(); return null; });