Redis系列之常见数据类型应用场景
Redis支持多种数据类型,比如String、hash、list、Set、SortedSet、Streams、Bitmap、Hyperloglog、Geo(物理位置)等等,在官网也给出了说明,本博客就挑一些比较常有的数据类型说说,本文例子基于Redisson实现

String
简单介绍
在Redis中,所有的数据都是key-value的数据结构存储的,那么在Redis中这个string类型的value值只能存储String类型的数据?其实不然,redis中string类型的value值是可以支持多种类型的,比如String、Number、Float、Bits等等,但是最大还是只能存储512M。Redis中key也是string类型存储的,所以最大也只能存储512M
常见命令
set、get命令就不演示了,下面给出一些常有命令
批量设置多个key
mset tkey1 tvalue tkey2 111
批量获取多个key值
mget tkey1 tkey2
获取长度
strlen tkey
字符串后面追加内容
append tkey tstring
获取指定范围的字符
# 取0~3之间的字符,返回1tst
getrange tkey 0 3
key进行递增(整数)
# 返回1
incr ikey
# 递增指定大小的值,返回124
incrby ikey 124
key进行递增(浮点数)
# 设置初始浮点数值
set fkey 1.2
# 在原来基础上递增2.4,返回3.6
incryfloat fkey 2.4
加上key过期时间
expire tkey 10
分布式锁实现,set if not exists,可以使用setnx单个命令,也可以使用set结合nx命令来实现
# set tkey过期时间10秒,nx:如果键不存在时设置
set tkey aaa ex 10 nx
# setnx命令,相当于set和nx命令一起用
setnx tkey aaa
EX : 设置指定的到期时间(以秒为单位)。
PX : 设置指定的到期时间(以毫秒为单
NX : 仅在键不存在时设置键。
XX : 只有在键已存在时才设置。
String 更多指令请参考官网文档:https://redis.io/commands/?group=string
应用场景
对于Redis String类型的应用场景也比较多,比如很常有的做缓存处理,也可以用于分布式锁、分布式ID
分布式锁的实现主要依赖于命令
setnx
分布式ID主要是利用
incr这个命令
基于Redis实现一个分布式ID生成器
package com.example.redis.common.handlers;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* <pre>
* Redis分布式ID生成器
* </pre>
*
* <pre>
* 修改记录
* 修改后版本: 修改人: 修改日期: 2023/11/07 14:18 修改内容:
* </pre>
*/
@Component
public class RedisIdentifierGenerator implements IdentifierGenerator {
@Resource
private RedisTemplate redisTemplate;
@Override
public Number nextId(Object entity) {
String key = entity.getClass().getName();
return redisTemplate.opsForValue().increment(key);
}
}
Hash
简单介绍
Hash哈希,数据类型也是一种比较常见的数据结构,相对于Redis的string类型而言,其实就是多了一层key(field),所以说只要string类型适用的场景,hash都是支持的
常见命令
hash设置key为hkey,field为a的值
hset hkey a aaaa
获取hkey的field值
hget hkey a
设置多个field值
hmset hkey a 1 b 2 c 3 d 4
获取多个field值
hmget hkey a b c d
获取key所有的field
hkeys hkey
获取key所有field的值
hvals hkey
获取key所有fileld和值
hgetall hkey

给key某个字段field添加值
hincrby hkey a 10

对于Hash的更多命令,请参考:https://redis.io/commands/?group=hash
应用场景
对于hash的应用场景,其实只要redis string类型适用的,hash都是适用的,不过hash这种特殊的数据结构,还是适用于一些特殊场景的
- 存储一个对象类的数据,这个对象的多个字段就对应hash的field
- 存储一些统计类的数据,比如访问量、点击量等等
如图,如果要统计博客的pv、uv还有评论数量(evaluation_count),随着博客数量的增加存储到数据库里,后面肯定会查询比较慢,所以可以使用redis进行缓存

使用Redisson来写一个例子:
@Resource
private RedissonClient redissonClient;
@Test
void contextLoads() throws ExecutionException, InterruptedException {
RMap<Object, Object> redissonClientMap = redissonClient.getMap("recordMap");
Map<String,Integer> map = new HashMap<>();
map.put("pv" , 1000);
map.put("uv" , 1500);
map.put("evaluation_count",30)
redissonClientMap.putAll(map);
System.out.println(redissonClientMap.addAndGet("pv", 2));
}
List
简单介绍
redis中的数据类型存储有序的字符串列表,元素是可以重复,列表的最大长度为2^32-1个元素(4294967295),即每个列表超过40亿个元素
常见命令
左右添加元素
# 左边添加元素
lpush queueList a
lpush queueList b c
# 右边添加元素
rpush queueList d e
左右弹出第一条
# 左边弹出一个元素
lpop queueList
# 右边弹出一个元素
rpop queueList
左右弹出一个元素,并且设置超时,直到无数据弹出或者超时
blpop queueList 10
brpop queueList 10
应用场景
微信公众号、微博等消息流列表
RDeque<Object> recordList = redissonClient.getDeque("recordList");
recordList.addFirst("1.新闻1");
recordList.addFirst("2.新闻2");
recordList.addFirst("3.新闻3");
IntStream.range(0,3).forEach(a->{
System.out.println(recordList.poll());
});
消息队列,使用redis也可以实现消息队列,比如使用
rpush/lpop实现简单队列;blpop或者是brpop来实现阻塞读取队列;补充说明,同时stream、pub/sub(订阅发布模式)、sortedSet等等也是可以实现的不过还是不建议使用Redis来实现消息队列,因为我们已经有成熟的MQ框架,使用redis实现队列有可能有下面的问题:
- 存在内存,可能会有数据丢失,不能重复消费
- 消费后不能回应,没有ack确认机制
Set
简单介绍
Redis中的Set类型是无序集合,最大存储数量为2^32-1,大概有40亿左右,添加、删除元素的时间复杂度都是O(1)
常见命令
添加一个或者多个元素
sadd skey a b c d e f g h
获取所有的元素
smembers skey
获取集合元素的个数
scard skey
随机获取一个元素
srandmember skey
随机弹出一个元素
spop skey
弹出指定的元素
# 如果两个元素都有,返回2
srem skey a g
检查元素是否存在
# 元素存在返回1
sismember skey e
获取前一个集合有,而后面一个集合没有的元素
sdiff skey skey1
获取集合的交集
sinter skey skey1
获取集合的并集
sunion skey skey1
Set的更多命令请参考:https://redis.io/commands/?group=set
应用场景
抽奖程序,利用
spop跟standmember随机弹出元素RSet<String> recordSet = redissonClient.getSet("recordSet");
List<String> members = Lists.newArrayList("alice", "tim","tom" , "风清扬", "jack" );
recordSet.addAll(members);
RFuture<Set<String>> threeSet = recordSet.removeRandomAsync(3
);
RFuture<Set<String>> twoSet = recordSet.removeRandomAsync(2
);
RFuture<Set<String>> oneSet = recordSet.removeRandomAsync(1
);
System.out.println("三等奖:"+threeSet.get());
System.out.println("二等奖:"+twoSet.get());
System.out.println("一等奖:"+oneSet.get());
集合交集(sinter)、并集(sunion)的场景,可以实现共同关注等场景
RSet<Object> tom = redissonClient.getSet("tom");
tom.addAll(Lists.newArrayList("令狐冲","james","风清扬"));
RSet<Object> jack = redissonClient.getSet("jack");
jack.addAll(Lists.newArrayList("令狐冲","tim","jack"));
System.out.println("共同关注的人:"+tom.readIntersectionAsync("jack").get());
sadd 集合存储,实现点赞、签到的业务场景
Sorted Set(Zset)
简单介绍
相对于set来说,sorted set是一种有序的set,排序是根据每个元素的score排序的,score相同时根据key的ASCII码排序

常见命令
批量添加元素
zadd z1 10 a 20 b 30 c 40 d 50 e 60 f 70 g 80 h 90 i

根据分数从低到高
zrange z1 0 -1 withscore

根据分数从高到低
zrevrange z1 0 -1 withscores
根据分数范围取值
zrangebyscore z1 20 30
移除元素
zrem z1 i
获取有序集合个数
zcard z1
给某个元素加分值
zincrby z1 20 a
获取范围内的个数
zcount z1 50 60
返回指定元素的索引值
# 假如d元素排在第4位,索引值就返回3
zrank z1 d
获取元素的分数
zscore z1 h
Sorted Set的更多命令请参考:https://redis.io/commands/?group=sorted_set
应用场景
排行榜
RScoredSortedSet<String> school = redissonClient.getScoredSortedSet("school");
school.add(60, "tom");
school.add(60, "jack");
school.add(60, "tim");
school.addScore("tom", 20);
school.addScore("jack", 10);
school.addScore("tim", 30);
RFuture<Collection<ScoredEntry<String>>> collectionRFuture = school.entryRangeReversedAsync(0, -1);
Iterator<ScoredEntry<String>> iterator = collectionRFuture.get().iterator();
System.out.println("成绩从高到低排序");
while(iterator.hasNext()) {
ScoredEntry<String> next = iterator.next();
String value = next.getValue();
System.out.println(value);
}
RFuture<Collection<ScoredEntry<String>>> collectionRFuture1 = school.entryRangeReversedAsync(0, 2);
Iterator<ScoredEntry<String>> iterator1 = collectionRFuture1.get().iterator();
System.out.println("成绩前三名");
while (iterator1.hasNext()) {
System.out.println(iterator1.next().getValue());
}
Bitmap
简单介绍
位图不是实际的数据类型,而是String类型中定义的一种面向位的操作,所以这个位图的最大存储量也是512M。可以容纳最少2^32不同的位,可以在不同的位置设置0或者1
常见命令
设置位的值
# 将位2设置为1
setbit permit 2 1
获取位的值
getbit permit 2

获取key的为1的个数
# 获取位为1的总数
bitcount permit
获取0或者1的第一位
# 获取key permit 位为1的第一个位置
bitpos permit 1

获取多个bitmap的位操作,比如& 、|
# 获取bkey和permit这两个的&运算,并且赋值给hbit
bitop AND hbit bkey permit

应用场景
实时的数据统计
比如:人员的考勤打卡记录,例如学生tom每次来上课就将相关的位记录位1
假如当月的第一天、第五天、第十天都来了
setbit tom 1 1
setbit tom 5 1
setbit tom 10 1
如何每月考勤,统计一下这个用户当月来了几天
bitcount tom
也可以应用于统计一个网站一天有多少用户访问,例如用户ID为123、124、125的用户访问了csdn
setbit csdn:2023-11-08 123 1
setbit csdn:2023-11-08 124 1
setbit csdn:2023-11-08 125 1
...
# 统计一下当天的访问次数
bitcount csdn:2023-11-08
- 存储用户权限,比如用1来表示有权限,0表示没权限,使用位图可以节省很大的存储空间
附录
Redis命令查询网站:https://redis.io/commands/

Redis系列之常见数据类型应用场景的更多相关文章
- Redis系列(2)之数据类型
Redis系列(2)之数据类型 <Redis系列(1)之安装>中介绍了Redis支持以下几种数据类型,那么本节主要介绍学习下这几种数据类型的基本操作 字符串类型,string 散列类型,h ...
- Redis全方位详解--数据类型使用场景和redis分布式锁的正确姿势
一.Redis数据类型 1.string string是Redis的最基本数据类型,一个key对应一个value,每个value最大可存储512M.string一半用来存图片或者序列化的数据. 2.h ...
- Redis系列---操作命令及数据类型
本章将简单介绍下,Redis里面常用的数据类型以及我们常用到的一些命令,let's go 准备环境: Redis 详细见上一个章节 我们接下来操作的命令用的是Redis自带的客户端工具,在安装red ...
- Redis系列之----Redis的数据类型及使用场景
Redis是一个开源的.高性能的.基于键值对的缓存与存储系统,能够提供多种不同的键值数据类型来适应不同场景下的缓存和存储需求. Redis中所有的数据都存储在内存中,因此读写速度非常快,相 ...
- Redis常见的应用场景解析
Redis是一个key-value存储系统,现在在各种系统中的使用越来越多,大部分情况下是因为其高性能的特性,被当做缓存使用,这里介绍下Redis经常遇到的使用场景. Redis特性 一个产品的使用场 ...
- Redis系列(二):Redis的数据类型及命令操作
原文链接(转载请注明出处):Redis系列(二):Redis的数据类型及命令操作 Redis 中常用命令 Redis 官方的文档是英文版的,当然网上也有大量的中文翻译版,例如:Redis 命令参考.这 ...
- 《【面试突击】— Redis篇》--Redis都有哪些数据类型?分别在哪些场景下使用比较合适?
能坚持别人不能坚持的,才能拥有别人不能拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>--Redis都有哪些数据类型?分别在哪些场景下使用 ...
- Redis系列(二)—— 数据类型及其使用
Redis数据类型及其使用 参考:http://www.cnblogs.com/jackluo/p/3173436.html Redis支持五种数据类型:string(字符串),hash(哈希),li ...
- redis的五种常见数据类型的常用指令
一.String字符串,key-value 应用场景:string是redis的最基本数据类型,key-value格式,一个key对应一个值的情况下 1.设置key = value:set key ...
- 3.redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
作者:中华石杉 面试题 redis 都有哪些数据类型?分别在哪些场景下使用比较合适? 面试官心理分析 除非是面试官感觉看你简历,是工作 3 年以内的比较初级的同学,可能对技术没有很深入的研究,面试官才 ...
随机推荐
- js闭包的一些笔记
闭包 闭包是一个可以访问外部作用域的内部函数,即使这个外部作用域已经执行结束 作用域 作用域决定这个变量的生命周期及其可见性.当我们创建一个函数,就会生成一个新的作用域. 通过var创建的变量只有函数 ...
- React: React-Router嵌套路由 exact问题
说明 当使用嵌套路由时,不能在父路由中添加exact,因为要先匹配父路由才能匹配子路由 父路由 子路由 效果如下所示 参考链接 https://www.jianshu.com/p/8bc3251079 ...
- ChatGPT插件开发实战
1.概述 ChatGPT是一款由OpenAI推出的先进对话模型,其强大的自然语言处理能力使得它成为构建智能对话系统和人机交互应用的理想选择.为了进一步拓展ChatGPT的功能和适应不同领域的需求,Op ...
- Kitex微服务开发实践(ETCD服务注册)
服务注册通常用于分布式系统或微服务架构中,是一种用于管理和发现这些分布式服务的机制.它的目标是让服务能够动态地找到其他服务,并能够与其进行通信,而无需显式地配置其位置信息 本文简单讲述使用etcd进行 ...
- 五 Android Capabilities讲解(转)
1.Capabilities介绍 可以看下之前代码里面设置的capabilities DesiredCapabilities capabilities = new DesiredCapabilitie ...
- .Net Web API 005 Controller上传小文件
1.附属文件对象定义 一般情况下,系统里面的文件都会附属一个对象存在,例如用户的头像文件,会附属用户对象存在.邮件中的文件会附属邮件存在.所以在系统里面,我们会创建一个附属文件对象,命名为Attach ...
- 「Go笔记-02」变量、数据类型、数据类型间转换、进制转换...看这一篇就Go了
前言 一个程序就是一个世界,不论是使用哪种高级程序语言编写程序, 变量都是其程序的基本组成单位, 变量 在 go 中 变量是用于存储数据的命名空间(内存位置),它可以表示一个值,这个值在程序执行过程中 ...
- LabVIEW图形化的AI视觉开发平台(非NI Vision)VI简介
前言 今天想和大家分享的是:仪酷LabVIEW AI视觉工具包的VI简介,如介绍内容有误,欢迎各位朋友们帮忙纠正~ 一.AI视觉工具包VI简介 已经安装好的AI工具包位于程序框图-函数选板-Addon ...
- 【路由器】OpenWrt 配置使用
目录 Web 界面 汉化 root 密码 ssh 升级 LuCI 美化 锐捷认证 MentoHUST MiniEAP 防火墙 开放端口 端口转发 IPv6 USB 安装 USB 驱动 自动挂载 Ext ...
- Jmeter+Ant+Jenkins接口自动化框架(续)
前段时间给公司内部项目搭建了一套接口自动化框架,基于实际使用,需要配置自动发送邮件功能,将 执行结果发送给相关负责人.Jenkins本身也提供了一个邮件通知功能,但在提供详细的邮件内容.自定义邮 件格 ...