Redis篇-9--数据结构篇1--五种基本结构(String,List,Set,Sorted Set,Hash,BLPOP阻塞逻辑)

Redis 是一个高性能的键值存储系统,支持多种数据结构。每种数据结构都有其独特的特点和适用场景。

1、String(字符串)

(1)、特点

  • 最简单的数据类型:字符串是最基本的数据类型,可以存储字符串、整数或浮点数。最大长度为 512 MB。
  • 支持原子操作:Redis 提供了多种原子操作,如递增、递减、追加字符串等。
  • 持久化支持:字符串可以持久化到磁盘,确保数据不会因服务器重启而丢失。

(2)、适用场景

  • 缓存:用于缓存网页内容、API 响应等。
  • 计数器:用于实现计数器功能,如点赞数、访问量等。
  • 会话管理:用于存储用户会话信息,如登录状态、购物车等。

(3)、redis-cli示例

1、设置键 “name” 的值为 “Alice”
SET name “Alice”
2、获取键 “name” 的值
GET name
在这里插入图片描述
3、递增键 “counter” 的值
INCR counter
4、递减键 “counter” 的值
DECR counter
在这里插入图片描述
5、追加字符串到键 “message”
APPEND message " Hello, World!"
在这里插入图片描述

(4)、Java示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class StringService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void setString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);   // 设置key
    }

    public String getString(String key) {
        return redisTemplate.opsForValue().get(key);    // 获取key的值
    }

    public Long incrementCounter(String key) {
        return redisTemplate.opsForValue().increment(key);   // 自增某key的值
    }

    public Long decrementCounter(String key) {
        return redisTemplate.opsForValue().decrement(key);   // 自减某key的值
    }

    public void appendString(String key, String value) {
        redisTemplate.opsForValue().append(key, value);  // 追加某key的值
    }
}

2、List(列表)

双端链表,可以从两端插入和删除元素。适用于队列和栈的实现。

(1)、特点

  • 双向链表:列表是一个双向链表,支持从两端插入和删除元素。可以在列表的头部(左端)或尾部(右端)进行操作。
  • 先进先出(FIFO)和后进先出(LIFO):可以通过不同的命令实现队列(FIFO)或栈(LIFO)的行为。
  • 阻塞操作:Redis 提供了阻塞式命令,如 BLPOP 和 BRPOP,可以在没有元素时阻塞等待,适用于消息队列场景。

解释一下如BLPOP的阻塞行为:
1、会阻塞其他客户端的请求吗?
答案:不会,其他客户端可以继续正常访问 Redis。
简单说:redis虽然只有一个线程处理命令,但它内部不是使用悲观锁处理数据安全问题,而是采取乐观锁的思路去解决的。对于暂时阻塞的请求可以迅速得到阻塞结果,将阻塞请求挂起,继续执行其他客户端的请求。所以可以同时处理多个客户端的请求。
具体解释:
(1)、Redis 使用单线程来处理所有命令的执行。这意味着在同一时间点上,Redis 只能处理一个命令。然而,Redis 的设计非常高效,能够快速处理每个命令,即使是阻塞的命令也会迅速快得到阻塞的结果,因此在大多数情况下,用户感觉不到延迟。

(2)、Redis是使用多路复用(multiplexing)技术来管理多个客户端连接。每个客户端的请求都被放入事件队列中,Redis 会依次处理这些请求。

(3)、Redis处理事件队列中请求的逻辑是使用了非阻塞 I/O 和事件循环(epoll、kqueue 等),这使得它可以在等待当前任务 I/O 操作完成时,同时继续处理其他其他客户端的请求。

(4)、因此,即使一个客户端被 BLPOP 阻塞,Redis 仍然可以处理来自其他客户端的请求。被 BLPOP 阻塞的请求会被暂时挂起,直到获取到元素或超时。

2、会阻塞当前客户端之后的请求吗?
答案:,该客户端之后的请求将无法在同一连接上继续执行。即一个客户端的一个连接是一个通道,如果通道内阻塞则会阻塞。但是同一个客户端可以和redis建立多个连接。
解释:
因为在 Redis 的单线程模型中,每个客户端连接是串行处理的,即在一个连接上,Redis 会等待当前命令(如 BLPOP)完成或超时后,才会处理该连接上的下一个命令。
但如果是同一个客户端的其他连接则不会被阻塞。

3、如果阻塞的连接断开了,阻塞的请求会怎样?
答案:请求会立即取消,即使是阻塞的请求。
解释:
当 Redis 客户端与 Redis 服务器之间的连接断开时,所有正在该连接上执行的命令(包括阻塞命令如 BLPOP、BRPOP、BZPOPMIN 等)都会被中断。
即:Redis 服务器会立即取消该连接上的所有未完成的命令,包括正在阻塞的命令(如 BLPOP)。这意味着 Redis 不会继续等待这些命令的结果,而是会立即释放与该连接相关的所有资源,包括内存中的临时数据结构(如阻塞队列中的等待状态)。因此,一旦连接断开,Redis 不会保留任何与该连接相关的信息。

(2)、适用场景

  • 消息队列:用于实现任务队列、消息队列等。
  • 历史记录:用于存储用户的操作历史、聊天记录等。
  • 最近使用列表:用于实现 LRU(Least Recently Used)缓存机制。

(3)、redis-cli示例

向列表 “queue1” 的尾部添加元素
RPUSH queue1 task1

向列表 “queue1” 的头部添加元素
LPUSH queue1 task0

从列表 “queue1” 的头部取出元素
LPOP queue1

从列表 “queue1” 的尾部取出元素
RPOP queue1

获取列表 “queue1” 的所有元素 // redis的列表,都是0作为第一个元素的索引
LRANGE queue1 0 -1

阻塞式从列表 “queue” 的头部取出元素(超时 5 秒)
BLPOP queue1 5
在这里插入图片描述

(4)、Java示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class ListService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private final ListOperations<String, Object> listOps;

    public ListService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.listOps = redisTemplate.opsForList();     // 指定list命令
    }

    public void pushToListRight(String key, Object value) {
        listOps.rightPush(key, value);    // 队尾添加value
    }

    public void pushToListLeft(String key, Object value) {
        listOps.leftPush(key, value);     // 队首添加value
    }

    public Object popFromListLeft(String key) {
        return listOps.leftPop(key);     // 队首取出一个元素
    }

    public Object popFromListRight(String key) {
        return listOps.rightPop(key);    // 队尾取出一个元素
    }

    public List<Object> rangeFromList(String key, long start, long end) {
        return listOps.range(key, start, end);    // 查询队列(0,-1)为查询全部
    }

    public Object blockPopFromListLeft(String key, long timeout, TimeUnit unit) {
        return listOps.leftPop(key, timeout, unit);   // 阻塞获取元素,设置超时时间
    }
}

3、Set(集合)

(1)、特点

  • 无序集合:集合是一个无序的集合,不允许重复元素。每个元素是唯一的。
  • 高效去重:集合非常适合用于去重操作,如获取多个集合的交集、并集、差集等。
  • 成员检查:可以快速检查某个元素是否存在于集合中。

(2)、适用场景

  • 去重:用于去除重复数据,如用户好友列表、标签系统等。
  • 唯一性验证:用于确保某个元素在集合中只出现一次,如黑名单、白名单等。
  • 集合运算:用于执行集合的交集、并集、差集等操作,如推荐系统中的共同爱好的好友等。

(3)、redis-cli示例

向集合 “users” 添加元素 “Alice”
SADD users Alice

检查元素 “Alice” 是否存在于集合 “users”
SISMEMBER users Alice

获取集合 “users” 中的所有元素
SMEMBERS users

从集合 “users” 中随机移除一个元素
SPOP users
在这里插入图片描述

获取两个集合 “users” 和 “admins” 的交集
SINTER users admins

获取两个集合 “users” 和 “admins” 的并集
SUNION users admins

获取两个集合 “users” 和 “admins” 的差集 // 即前者独有的元素有哪些
SDIFF users admins
在这里插入图片描述

(4)、Java示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class SetService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private final SetOperations<String, Object> setOps;

    public SetService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.setOps = redisTemplate.opsForSet();    // 指定set操作
    }

    public void addElementToSet(String key, Object... values) {
        setOps.add(key, values);        // 添加元素
    }

    public boolean isMemberOfSet(String key, Object value) {
        return setOps.isMember(key, value);       // 是否包含value元素
    }

    public Set<Object> getMembersOfSet(String key) {
        return setOps.members(key);    // 获取set集合
    }

    public Object popRandomElementFromSet(String key) {
        return setOps.pop(key);      // 随机取set中的一个元素
    }

    public Set<Object> intersectSets(String... keys) {
        return setOps.intersect(keys);      // 交集
    }

    public Set<Object> unionSets(String... keys) {
        return setOps.union(keys);        // 并集
    }

    public Set<Object> differenceSets(String... keys) {
        return setOps.difference(keys);          // 差集
    }
}

4、Sorted Set(有序集合)

(1)、特点

  • 带分数的集合:有序集合是一个带分数的集合,每个元素都有一个关联的分数(score),根据分数进行排序。
  • 范围查询:可以基于分数或排名进行范围查询,如获取前 N 个最高分的用户。
  • 高效插入和删除:有序集合支持高效的插入、删除和查找操作,适用于需要排序的场景。

(2)、适用场景

  • 排行榜:用于实现排行榜功能,如游戏得分榜、热门文章排行等。
  • 时间序列数据:用于存储带有时间戳的数据,如日志、事件流等。
  • 优先级队列:用于实现优先级队列,如任务调度系统。

(3)、redis-cli示例

向有序集合 “leaderboard” 添加元素 “Alice”,分数为 100
ZADD leaderboard 100 Alice

获取有序集合 “leaderboard” 中排名前 3 的元素
ZRANGE leaderboard 0 2 WITHSCORES

获取有序集合 “leaderboard” 中分数在 50 到 150 之间的元素
ZRANGEBYSCORE leaderboard 50 150 WITHSCORES

获取元素 “Alice” 在有序集合 “leaderboard” 中的排名
ZRANK leaderboard Alice

递增元素 “Alice” 的分数
ZINCRBY leaderboard 10 Alice
在这里插入图片描述

(4)、Java示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class SortedSetService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private final ZSetOperations<String, Object> zSetOps;

    public SortedSetService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.zSetOps = redisTemplate.opsForZSet();    // 指定zset操作
    }

    public void addElementToSortedSet(String key, Object value, double score) {
        zSetOps.add(key, value, score);   // 添加元素和排名
    }

    public Set<ZSetOperations.TypedTuple<Object>> rangeByScore(String key, double min, double max) {
        return zSetOps.rangeByScoreWithScores(key, min, max);   // 获取指定区间的排名
    }

    public Set<Object> rangeByRank(String key, long start, long end) {
        return zSetOps.range(key, start, end);
    }

    public Long getRankInSortedSet(String key, Object value) {
        return zSetOps.rank(key, value);
    }

    public Double incrementScore(String key, Object value, double increment) {
        return zSetOps.incrementScore(key, value, increment);
    }
}

5、Hash(哈希表)

(1)、特点

  • 键值对集合:哈希是一个键值对的集合,非常适用于存储对象。每个哈希字段(field)对应一个值(value),并且可以独立操作。
  • 高效存储:哈希适合存储复杂的对象结构,且占用较少的内存空间。
  • 原子操作:可以对哈希中的字段进行原子操作,如增加、删除、获取单个字段或多字段。

(2)、适用场景

  • 对象存储:用于存储对象的属性,如用户信息、商品详情等。
  • 配置管理:用于存储应用程序的配置项。
  • 会话管理:用于存储用户的会话信息,如登录状态、权限等。

(3)、redis-cli示例

1、设置哈希 “user:1001” 的字段 “name” 为 “Alice”
HSET user:1001 name “Alice”

2、获取哈希 “user:1001” 的字段 “name”
HGET user:1001 name

3、获取哈希 “user:1001” 的所有字段和值
HGETALL user:1001

4、删除哈希 “user:1001” 的字段 “age”
HDEL user:1001 age

5、检查哈希 “user:1001” 是否存在字段 “name”
HEXISTS user:1001 name
在这里插入图片描述

(4)、Java示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class HashService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private final HashOperations<String, String, Object> hashOps;

    public HashService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.hashOps = redisTemplate.opsForHash();    // 指定hash命令操作
    }

    public void setHashField(String key, String field, Object value) {
        hashOps.put(key, field, value);    // 设置key对象的field属性为value值
    }

    public Object getHashField(String key, String field) {
        return hashOps.get(key, field);  // 获取key对象的field属性值
    }

    public Map<String, Object> getAllHashFields(String key) {
        return hashOps.entries(key);    // 获取key对象的全部属性值
    }

    public void deleteHashField(String key, String field) {
        hashOps.delete(key, field);    // 删除key对象的field属性
    }

    public boolean existsHashField(String key, String field) {
        return hashOps.hasKey(key, field);   // 校验key对象是否存在field属性
    }
}

学海无涯苦作舟!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/935255.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

优雅的@ObservedV2和@Trace装饰器

Hello&#xff0c;大家好&#xff0c;我是 V 哥。在HarmonyOS NEXT开发中&#xff0c;ObservedV2装饰器和Trace装饰器是用于状态管理的两个装饰器&#xff0c;它们在HarmonyOS应用开发中用于增强对类对象中属性的观测能力。如果你学过观察者模式的原理&#xff0c;你会更容易理…

物联网安全-ARMv8-M Trustzone 实操

前言 本文针对ARMv8m架构M23/M33 MCU安全特性使用进行介绍,以nxp LPC55xx系列和STM32L5xx系列为例,为大家阐述如何使用Trustzone技术提高物联网设备安全性,适合有一定平台安全基础的物联网设备开发人员、安全方案开发人员。 背景 为了提升平台安全性,ARM推出了ARMv8m架构…

昱感微“多维像素”多模态融合感知展示

昱感微采用“多维像素”多模态融合技术&#xff0c;将可见光摄像头、红外摄像头、4D毫米波雷达/激光雷达的探测数据以“多维像素”的数据格式输出&#xff1a;图像数据雷达探测数据红外传感器探测数据叠加&#xff0c;以摄像头像素为颗粒度组合全部感知数据&#xff0c;形成多模…

Launcher添加hotseat图标布局

Launcher的hotseat客户要求添加一些指定应用图标。 首先打开机器将要布局的图标手动移动到hotseat位置上面。 然后使用adb命令将data/data/com.android.launcher3/databases这个文件pull出来。这个文件夹是Luancher的数据库文件。里面保存了相关应用的图标信息。 使用SQLiteS…

GNSS误差源及差分定位

GNSS误差源&#xff1a; &#xff08;一&#xff09;卫星星历误差 由星历信息所得出的卫星位置坐标与实际位置坐标的偏差就是星历误差。星历信息是由 GPS 地面部分测量计算后传入空间部分的。由于卫星在运动中要受到各种摄动力的作用, 而地面部分又很难精确测量这些作用力,…

【数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;实现希尔排序算法。 测试说明 平台会对你编写的代码进行测试&#xff1a; 测试输入示例&#xff1a; 10 9 8 7 6 5 4 3 2 1 0 (说明&#xff1a;第一行是元素个数&a…

通俗易懂的 Nginx 反向代理 配置

通俗易懂的 Nginx 反向代理 配置 首先 root 与 alias 的区别 root 是直接拼接 root location location /i/ {root /data/w3; }当请求 /i/top.gif &#xff0c;/data/w3/i/top.gif 会被返回。 alias 是用 alias 替换 location location /i/ {alias /data/w3/images/; }当请…

网页爬虫技术全解析:从基础到实战

引言 在当今信息爆炸的时代&#xff0c;互联网上的数据量每天都在以惊人的速度增长。网页爬虫&#xff08;Web Scraping&#xff09;&#xff0c;作为数据采集的重要手段之一&#xff0c;已经成为数据科学家、研究人员和开发者不可或缺的工具。本文将全面解析网页爬虫技术&…

分页查询和事务管理

前端需要给后端传递的参数&#xff1a; page&#xff1a;当前页码&#xff0c;用于指定用户想要查看的页。pageSize&#xff1a;每页展示记录数&#xff0c;用于指定每页应显示多少条记录。 后端需要给前端返回的结果&#xff1a; total&#xff1a;总记录数&#xff0c;用于告…

MATLAB深度学习(七)——ResNet残差网络

一、ResNet网络 ResNet是深度残差网络的简称。其核心思想就是在&#xff0c;每两个网络层之间加入一个残差连接&#xff0c;缓解深层网络中的梯度消失问题 二、残差结构 在多层神经网络模型里&#xff0c;设想一个包含诺干层自网络&#xff0c;子网络的函数用H(x)来表示&#x…

go语言zero框架调用自己的安装的redis服务配置与使用

在 Go 语言中调用自己安装的 Redis 服务&#xff0c;可以分为几个步骤&#xff1a;从安装 Redis 服务到配置、启动 Redis&#xff0c;最后在 Go 代码中连接并使用 Redis。以下是详细的步骤&#xff1a; ## 1. 安装 Redis 服务 ### 1.1 在 Linux 系统上安装 Redis 假设你使用…

Cerebras 推出 CePO,填补推理与规划能力的关键空白

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Google Cloud Database Option(数据库选项说明)

关系数据库 在关系数据库中&#xff0c;信息存储在表、行和列中&#xff0c;这通常最适合结构化数据。因此&#xff0c;它们用于数据结构不经常更改的应用程序。与大多数关系数据库交互时使用 SQL&#xff08;结构化查询语言&#xff09;。它们为数据提供 ACID 一致性模式&am…

ArcGIS将MultiPatch数据转换为Obj数据

文章目录 ArcGIS将MultiPatch数据转换为Obj数据1 效果2 技术路线2.1 Multipatch To Collada2.2 Collada To Obj3 代码实现4 附录4.1 环境4.2 一些坑ArcGIS将MultiPatch数据转换为Obj数据 1 效果 2 技术路线 MultiPatch --MultipatchToCollada–> Collada --Assimp–> O…

微信小程序5-图片实现点击动作和动态加载同类数据

搜索 微信小程序 “动物觅踪” 观看效果 感谢阅读&#xff0c;初学小白&#xff0c;有错指正。 一、功能描述 a. 原本想通过按钮加载背景图片&#xff0c;来实现一个可以点击的搜索button&#xff0c;但是遇到两个难点&#xff0c;一是按钮大小调整不方便&#xff08;网上搜索…

使用nmap确定扫描目标

nmap可以通过IP、主机名、域名等指定单一目标&#xff0c;也可以使用IP范围、列表文件、等指定多个IP。 单一目标 IP nmap IP主机名 nmap hostname域名 nmap domainname&#xff0c;可以通过--dns-server指定dns服务器地址&#xff0c;也可以通过--system-dns指定使用操作系统…

【C++】关联存储结构容器-set(集合)详解

目录 一、基本概念 二、内部实现 三、常用操作 3.1 构造函数 3.2 插入操作 3.3 删除操作 3.4 查找操作 3.5 访问元素 3.6 容量操作 3.7 交换操作 四、特性 五、应用场景 结语 一、基本概念 set是C标准模板库&#xff08;STL&#xff09;中的一种关联容器&#xf…

ssm-day03 aoptx

AOP AOP指的是面向对象思想编程问题的一些补充和完善 soutp、soutv 解耦通俗理解就是把非核心代码剥出来&#xff0c;减少对业务功能代码的影响 设计模式是解决某些特定问题的最佳解决方案&#xff0c;后面一点要记得学这个&#xff01;&#xff01;&#xff01; cxk唱跳哈…

谷粒商城—分布式高级①.md

1. ELASTICSEARCH 1、安装elastic search dokcer中安装elastic search (1)下载ealastic search和kibana docker pull elasticsearch:7.6.2 docker pull kibana:7.6.2(2)配置 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data echo "h…

数据仓库的性能问题及解决之道

随着数据量不断增长和业务复杂度逐渐攀升&#xff0c;数据处理效率面临巨大挑战。最典型的表现是面向分析型场景的数据仓库性能问题越来越突出&#xff0c;压力大、性能低&#xff0c;查询时间长甚至查不出来&#xff0c;跑批跑不完造成生产事故等问题时有发生。当数据仓库出现…