Redis入门(九)

embedded/2024/11/24 15:44:18/

Redis地理空间(GEO)

简介

从版本 3.2 开始,Redis 引入了地理空间支持,允许用户在 Redis 中存储地理位置信息,并执行一些与地理位置相关的操作。

原理

将球体转换为平面,区块转换为一点 

 

基本命令 

1.GEOADD - 将一个或多个地理位置元素添加到指定的键中。每个位置由经度、纬度和成员名称组成。

  • 用途:将一个或多个地理位置元素添加到指定的键中。
  • 语法:GEOADD key longitude latitude member [longitude latitude member ...]
  • 示例
> GEOADD places 116.404 39.915 "Beijing"
(integer) 1
> GEOADD places -73.993 40.750 "New York"
(integer) 1

2.GEODIST - 计算两个给定成员之间的距离。可以使用不同的单位来返回结果(例如米、千米、英里等)。

  • 用途:计算两个给定成员之间的距离。
  • 语法GEODIST key member1 member2 [unit]
  • 单位m(米)、km(千米)、mi(英里)、ft(英尺)
  • 示例
> GEODIST places Beijing New York km
"10684.4115"

3.GEOPOS - 获取一个或多个成员的位置(即经度和纬度)。

  • 用途:获取一个或多个成员的位置(即经度和纬度)。
  • 语法GEOPOS key member [member ...]
  • 示例:
> GEOPOS places Beijing
1) 1) "116.40400000000000178698"2) "39.91499999999999943155"

4.GEORADIUS - 在给定的地理位置周围查找所有成员,这些成员位于指定半径内。可以以米或千米为单位指定半径。

  • 用途:在给定的地理位置周围查找所有成员,这些成员位于指定半径内。
  • 语法GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
  • 示例
> GEORADIUS places 116.404 39.915 100 km WITHDIST
1) 1) "Beijing"2) "0.0000"

5.GEORADIUSBYMEMBER - 类似于 GEORADIUS,但是是以另一个成员的位置为中心来查找附近的其他成员。

  • 用途:类似于 GEORADIUS,但以另一个成员的位置为中心来查找附近的其他成员。
  • 语法:GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
  • 示例
> GEORADIUSBYMEMBER places Beijing 100 km WITHDIST
1) 1) "Beijing"2) "0.0000"
  •  参数说明

        WITHCOORD:返回每个成员的经度和纬度。
        WITHDIST:返回每个成员与中心点的距离。
        WITHHASH:返回每个成员的 Geohash 整数值。
        COUNT count:限制返回的结果数量。
        ASC/DESC:按距离升序或降序排列结果。
        STORE key:将结果存储到指定的键中。
        STOREDIST key:将结果的距离存储到指定的键中。

6.GEOHASH - 返回一个或多个位置元素的Geohash表示。

  • 用途:用来表示一个地理位置的大致范围。
  • 语法:GEOHASH key member [member ...]
  • 示例
# 查找距离北京 100 公里内的所有地点
> GEORADIUS places 116.404 39.915 100 km WITHDIST
1) 1) "Beijing"2) "0.0000"

数据存储 

地理空间数据在 Redis 中是作为有序集合(sorted set)存储的。每个地理位置都有一个唯一的分数,这个分数是由地理位置的经度和纬度计算得出的。因此,Redis 能够高效地处理地理位置的查询。 

 应用场景

附近的人/地点搜索 : 可以快速找到某个地理位置周围的用户或兴趣点。
路径规划 : 虽然 Redis 不直接支持复杂的路径规划算法,但它可以用来辅助计算两点之间的直线距离。
地理围栏 : 当用户进入或离开特定区域时触发事件。 

Redis 流(Stream)

简介 

Redis 流(Stream)是从 Redis 5.0 版本开始引入的一种新的数据类型,用于处理实时数据流。流(Stream)数据类型非常适合用于构建消息队列日志记录系统事件溯源等应用场景。

主要特性

持久化:流中的数据会被持久化存储,即使 Redis 重启后数据也不会丢失。
追加只读:流是一个追加只读的数据结构,只能在尾部添加新数据,不能修改已有的数据。
多消费者组:支持多个消费者组(Consumer Groups),每个组可以有多个消费者(Consumers),实现消息的分布式消费。
消息确认:消费者可以确认已经处理的消息,未确认的消息可以被重新消费。
历史消息保留:可以根据需要配置保留一定数量的历史消息,超出的部分会被自动删除。 

底层结构

 一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。

1Message Content消息内容
2Consumer group消费组,通过XGROUP CREATE 命令创建,同一个消费组可以有多个消费者
3Last_delivered_id游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
4Consumer消费者,消费组中的消费者
5Pending_ids消费者会有一个状态变量,用于记录被当前消费已读取但未ack的消息Id,如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack它就开始减少。这个pending_ids变量在Redis官方被称之为 PEL(Pending Entries List),记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符),它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理

 

常用命令 

 队列相关指令

1. XADD
  • 用途:向流中添加一条消息。如果指定的Stream 队列不存在,则该命令执行时会新建一个Stream 队列.
  • 语法:XADD key [MAXLEN/LIMIT] count message
  • 示例: 
> XADD mystream * sensor-id 1234 temperature 19.8
1626893541302-0

 * 表示让 Redis 自动生成一个唯一的消息 ID。类似mysql里面主键auto_increment,后面顺序跟着一堆业务key/value。
sensor-id 1234 temperature 19.8 是消息的内容,键值对形式。

信息条目指的是序列号,在相同的毫秒下序列号从0开始递增,序列号是64位长度,理论上在同一毫秒内生成的数据量无法到达这个级别,因此不用担心序列号会不够用。millisecondsTime指的是Redis节点服务器的本地时间,如果存在当前的毫秒时间戳比以前已经存在的数据的时间戳小的话(本地时间钟后跳),那么系统将会采用以前相同的毫秒创建新的ID,也即redis 在增加信息条目时会检查当前 id 与上一条目的 id, 自动纠正错误的情况,一定要保证后面的 id 比前面大,一个流中信息条目的ID必须是单调增的,这是流的基础。
客户端显示传入规则:
Redis对于ID有强制要求,格式必须是 时间戳-自增Id这样的方式,且后续ID不能小于前一个ID
Stream的消息内容,也就是图中的Message Content它的结构类似Hash结构,以key-value的形式存在。
2. XREAD
  •  用途:从一个或多个流中读取消息。只会返回大于指定ID的消息。
  • 语法:XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]
  • 示例:
> XREAD COUNT 2 STREAMS mystream 0
1) 1) "mystream"2) 1) 1) "1626893541302-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "19.8"2) 1) "1626893541303-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "20.1"

count表示最多可以读取多少条消息

BLOCK表示是否以阻塞的方式读取消息,默认不阻塞,如果 milliseconds设置为0,表示 永远阻塞。

$代表特殊ID,表示以当前Stream已经存储的最大的ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil
0-0代表从最小的ID开始获取Stream中的消息,当不指定count,将会返回Stream中的所有消息,注意也可以使用0(00/000也都是可以的……)

Stream的基础方法,使用xadd存入消息和xread循环阻塞读取消息的方式可以实现简易版的消息队列,交互流程如下:

3. XRANGE
  • 用途:按时间顺序返回流中的消息。
  • 语法:XRANGE key start end [COUNT count]
  • 示例:
> XRANGE mystream - +
1) 1) "1626893541302-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "19.8"
2) 1) "1626893541303-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "20.1"

 - 表示从最早的 ID 开始。
+ 表示到最新的 ID 结束。

4. XREVRANGE 
  • 用途:按逆时间顺序返回流中的消息。
  • 语法:XREVRANGE key end start [COUNT count]
  • 示例: 
> XREVRANGE mystream + -
1) 1) "1626893541303-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "20.1"
2) 1) "1626893541302-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "19.8"
5.XDEL 
  • 用途:删除流中的一个或多个消息。
  • 语法:XDEL key id [id ...]
  • 示例: 
> XDEL mystream 1626893541302-0
(integer) 1
6.XLEN
  • 用途:获取流中的消息数量。
  • 语法:XLEN key
  • 示例:
> XLEN mystream
(integer) 3

 如果尝试获取一个不存在的流的消息数量,XLEN 将返回 0。

消费组相关指令

1. XGROUP CREATE
  • 用途:创建一个新的消费者组。
  • 语法:XGROUP CREATE key groupname id-or-$
  • 示例: 
> XGROUP CREATE mystream group1 0
OK

group1 是消费者组的名称。
0 表示从最早的未确认消息开始消费。

$表示从Stream尾部开始消费

0表示从Stream头部开始消费

创建消费者组的时候必须指定 ID, ID 为 0 表示从头开始消费,为 $ 表示只消费新的消息,队尾新来

2. XREADGROUP 
  • 用途:从流中读取消息,支持消费者组。
  • 语法:XREADGROUP GROUP groupname consumername [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]
  • 示例: 
> XREADGROUP GROUP group1 consumer1 COUNT 2 STREAMS mystream >
1) 1) "mystream"2) 1) 1) "1626893541302-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "19.8"2) 1) "1626893541303-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "20.1"

 GROUP group1 consumer1 表示从 group1 消费者组中读取,consumer1 是消费者名称。
> 表示从最新的未确认消息开始消费。

stream中的消息一旦被消费组中的一个消费者读取,就不能被该消费组内的其他成员读取了,即同一个消费组里的消费者不能消费同一条消息,不同消费组的消费者可以消费同一条消息。

让组内的多个消费者共同分担读取消息,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的。

3. XACK 
  • 用途:确认消息已被成功处理。
  • 语法:XACK key groupname id [id ...]
  • 示例: 
> XACK mystream group1 1626893541302-0
(integer) 1
4. XINFO
  • 用途:获取流的各种信息。
  • 语法:XINFO subcommand key [extra arguments]
  • 示例: 
> XINFO STREAM mystream
1) length
2) (integer) 2
3) first-entry
4) 1) "1626893541302-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "19.8"
5) last-entry
6) 1) "1626893541303-0"2) 1) "sensor-id"2) "1234"3) "temperature"4) "20.1"
5.XPENDING
  • 用途:查询每个消费组内所有消费者[已读取,但尚未确认]的消息,或查看某个消费者具体读取了哪些数据。
  • 语法:XPENDING key groupname [start end count] [consumer]
  • 示例:
> XPENDING mystream group1 - + 10 consumer1
1) 1) "1626893541302-0"2) "consumer1"3) (integer) 10004) (integer) 1

 这表明 consumer1 有 1 条待处理消息。

 应用场景

消息队列:使用 Redis 流可以构建高性能的消息队列系统,支持多消费者组和消息确认机制。
日志记录:流可以用于记录应用程序的日志,支持按时间顺序读取和归档。
事件溯源:流可以用于记录系统的状态变化,支持历史数据的查询和分析。 

 

 


http://www.ppmy.cn/embedded/140154.html

相关文章

next build报错bash: next: command not found

相关背景:我有个next.js项目(第一次使用next.js框架),想构建一下,发现报错了,没有该命令。 (ps:我测试用的是:yarn dev) 然后我用everything全局搜了下 next…

9.局部变量和全局变量

局部变量 定义在函数体内部的变量,只在函数体内部生效。 全局变量 定义在函数体的外面的变量,所有的函数都可以使用。 global关键 函数内部声明的变量为全局变量。 函数里对全局变量进行修改,要想生效,需要用global声明。 …

uniapp接入BMapGL百度地图

下面代码兼容安卓APP和H5 百度地图官网:控制台 | 百度地图开放平台 应用类别选择《浏览器端》 /utils/map.js 需要设置你自己的key export function myBMapGL1() {return new Promise(function(resolve, reject) {if (typeof window.initMyBMapGL1 function) {r…

分类算法——基于heart数据集实现

1 heart数据集——描述性统计分析 import matplotlib.pyplot as plt import pandas as pd# Load the dataset heart pd.read_csv(r"heart.csv", sep,)# Check the columns in the DataFrame print(heart.columns)aheart.loc[:, y].value_counts() print(a) heart.l…

【C++】二叉搜索树详解:插入、删除、查找的最佳实践与优化策略

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 📘 基础数据结构【C语言】 💻 C语言编程技巧【C】 🚀 进阶C【OJ题解】 📝 题解精讲 目录 📌 前言📌 1 二叉搜索树的概念📌 2 二叉…

禁止Chrome的自动升级

一、需求分析 因为用Chromeselenium做了网页自动化填写任务,如果Google Chrome浏览器自动升级,就会导致chromedriver加载失败,自动化任务失效,因此需要禁止Chrome浏览器的自动升级。 二、当前环境 三、实际配置 运行注册表编辑…

企业OA管理系统:Spring Boot技术实践与案例分析

3系统分析 3.1可行性分析 通过对本企业OA管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业OA管理系统采用SSM框架,JAVA作为开发语言&a…

web——sqliabs靶场——第十五关——post时间盲注

还是post传参 搞了个高级的脚本,看看 #!/usr/bin/python3 # -*- coding: utf-8 -*-# 修改payload,data # 添加了time.sleep(0.05) # default # 修改时要注意间隔 import requests from optparse import OptionParser import time import threading# 存…