首页 > 数据库 >Redis系列之常见数据类型应用场景

Redis系列之常见数据类型应用场景

时间:2023-11-14 15:02:51浏览次数:40  
标签:redis 场景 命令 数据类型 元素 Redis 获取 key



文章目录

  • String
  • 简单介绍
  • 常见命令
  • 应用场景
  • Hash
  • 简单介绍
  • 常见命令
  • 应用场景
  • List
  • 简单介绍
  • 常见命令
  • 应用场景
  • Set
  • 简单介绍
  • 常见命令
  • 应用场景
  • Sorted Set(Zset)
  • 简单介绍
  • 常见命令
  • 应用场景
  • Bitmap
  • 简单介绍
  • 常见命令
  • 应用场景
  • 附录



Redis支持多种数据类型,比如String、hash、list、Set、SortedSet、Streams、Bitmap、Hyperloglog、Geo(物理位置)等等,在

官网也给出了说明,本博客就挑一些比较常有的数据类型说说,本文例子基于Redisson实现

Redis系列之常见数据类型应用场景_缓存

String

简单介绍

在Redis中,所有的数据都是key-value的数据结构存储的,那么在Redis中这个string类型的value值只能存储String类型的数据?其实不然,redis中string类型的value值是可以支持多种类型的,比如String、Number、Float、Bits等等,但是最大还是只能存储512M。Redis中key也是string类型存储的,所以最大也只能存储512M

常见命令

setget命令就不演示了,下面给出一些常有命令

批量设置多个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

Redis系列之常见数据类型应用场景_应用场景_02

给key某个字段field添加值

hincrby hkey a 10

Redis系列之常见数据类型应用场景_redis_03

对于Hash的更多命令,请参考:https://redis.io/commands/?group=hash

应用场景

对于hash的应用场景,其实只要redis string类型适用的,hash都是适用的,不过hash这种特殊的数据结构,还是适用于一些特殊场景的

  • 存储一个对象类的数据,这个对象的多个字段就对应hash的field
  • 存储一些统计类的数据,比如访问量、点击量等等

如图,如果要统计博客的pv、uv还有评论数量(evaluation_count),随着博客数量的增加存储到数据库里,后面肯定会查询比较慢,所以可以使用redis进行缓存

Redis系列之常见数据类型应用场景_缓存_04

使用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来实现阻塞读取队列;补充说明,同时streampub/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

应用场景

  • 抽奖程序,利用spopstandmember随机弹出元素
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码排序

Redis系列之常见数据类型应用场景_redis_05

常见命令

批量添加元素

zadd z1 10 a 20 b 30 c 40 d 50 e 60 f 70 g 80 h 90 i

Redis系列之常见数据类型应用场景_应用场景_06

根据分数从低到高

zrange z1 0 -1 withscore

Redis系列之常见数据类型应用场景_应用场景_07

根据分数从高到低

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

Redis系列之常见数据类型应用场景_Redis_08

获取key的为1的个数

# 获取位为1的总数
bitcount permit

获取0或者1的第一位

# 获取key permit 位为1的第一个位置
bitpos permit 1

Redis系列之常见数据类型应用场景_应用场景_09

获取多个bitmap的位操作,比如&|

# 获取bkey和permit这两个的&运算,并且赋值给hbit
bitop AND hbit bkey permit

Redis系列之常见数据类型应用场景_缓存_10

应用场景

  • 实时的数据统计
    比如:人员的考勤打卡记录,例如学生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系列之常见数据类型应用场景_数据库_11


标签:redis,场景,命令,数据类型,元素,Redis,获取,key
From: https://blog.51cto.com/u_15704340/8369457

相关文章

  • Redis系列之实现分布式自增主键
    软件环境JDK1.8SpringBoot2.2.1Maven3.2+Mysql8.0.26redis6.2.14MybatisPlus3.4.3.4开发工具IntelliJIDEAsmartGit一、实现原理使用Redis来实现分布式的主键自增主要是依赖于Redis的INCR命令,调用INCR命令的对应key,其数值是实现递增加一,所以利用这个性质,将redis独立部署起来......
  • 不务正业的再次胡想——chatgpt在“智能辅助编程”外的另一个可能场景"智能论文写作辅
    在chatgpt4出来后震惊了很多人,但是很多人也觉得好像用处不大;可以说chatgpt4确实更加智能了,在语言对话上更加的智能,很多情况下已经很难分辨出这货是个机器人,但是现在这东西好像确实也没有太多的实际应用,或许更多的人用这个是当做“智能搜索引擎”来用的,而我个人却更加喜欢将chatgpt......
  • Redission获取Redis时间
    RScriptscript=redissonClient.getScript(StringCodec.INSTANCE);longcurrentTime=script.eval(RScript.Mode.READ_WRITE,"localtime=redis.call('TIME')"+"localmilliseconds=tim......
  • redis 类型List增删查改效率
    Redis的List数据类型是一个双向链表,支持在列表的两端进行高效的插入和删除操作。下面是关于RedisList类型的增删查改操作的效率说明:1.增加元素(左侧和右侧添加):左侧添加(LPUSH)和右侧添加(RPUSH)都是O(1)时间复杂度的操作,它们可以在常数时间内完成,不受列表长度的影响。批量添加元素(例......
  • SpringBoot定义拦截器+自定义注解+Redis实现接口防刷(限流)
    实现思路在拦截器Interceptor中拦截请求通过地址+请求uri作为调用者访问接口的区分在Redis中进行计数达到限流目的简单实现定义参数访问周期最大访问次数禁用时长#接口防刷配置,时间单位都是秒.如果second秒内访问次数达到times,就禁用lockTime秒access:lim......
  • Redis简述|以及它能用于做什么?
    什么是RedisRedis是一种开源的NoSQL内存数据库,用于高性能的数据存储和访问。Redis支持多种数据类型,包括字符串、哈希、列表、集合和有序集合,并且支持分布式存储和操作。Redis的特点包括快速、高可用和易扩展等,适用于各种应用场景。Redis应用场景Redis可以广泛应用于多种场景,包括......
  • Redis各种集群搭建指南
    Redis集群本章是基于CentOS7下的Redis集群教程,包括:单机安装RedisRedis主从Redis分片集群1.单机安装Redis首先需要安装Redis所需要的依赖:yuminstall-ygcctcl例如,我放到了/tmp目录:解压缩:tar-xzfredis-6.2.4.tar.gz解压后:进入redis目录:cdredis-6.2.4运行编译命令:make&&makei......
  • 【Redis】Cluster集群模式
    (目录)RedisCluster集群模式Cluster模式是Redis3.0开始推出采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接官方要求:至少6个节点才可以保证高可用,即3主3从;扩展性强、更好做到高可用各个节点会互相通信,采用gossip协议交换节点元数据信息数......
  • 【Redis】详解 Redis哨兵(Sentinel)架构,Master 挂了的故障转移措施
    (目录)Redis哨兵(Sentinel)架构Redis主从复制一主多从架构master主要负责写入,slave负责读取,有读写分离的功能redis主从同步原理1、slave执行命令向master建立连接2、master执行bgsave(后台存储),生成rdb快照(redis备份方式,data以二进制方式保存在本地),发送到slave上3、sla......
  • 多态真的有用吗?使用在哪些场景?
    多态是面向对象编程(OOP)中的一个重要概念,它能够增加代码的灵活性和可维护性。多态的主要思想是同一个方法名在不同的类中有不同的实现,或者说同一个接口可以有多个不同的实现方式。让我们通过一个生动的例子来说明多态的用途。假设有一个图形类,其中包括圆形和矩形两个子类。每个图形......