Redis模块的高级使用方式

Redis 模块是Redis的高级功能,允许我们实现特定的自定义数据类型。本质上,模块是一个动态库,可以在启动时或根据命令按需加载到 Redis 中 MODULE LOAD 。模块可以用多种语言编写,包括 C 和 Rust。

我们自己使用 Redis 模块实现新的数据类型是一项艰巨的工作。值得庆幸的是,有许多流行且广泛使用的模块可以解决全文搜索(RediSearch)、时间序列处理(RedisTimeSeries)和原生 JSON 支持(RedisJSON)等问题。让我们概述一下一些使用更广泛的 Redis 模块。

本节提供了 RediSearch、RedisJSON 和 RedisTimeSeries 模块的高级概述,以及与它们相关的重要命令。

要完成本教程的这一部分,您需要 安装最新版本的 Go 和 Docker。所有上述模块都作为Redis Stack的一部分提供 ,它将 Redis 与各种相关的软件包和服务捆绑在一起。您可以使用 Docker 启动 Redis Stack 本地实例 :
docker run -d --name redis-stack -p 6379:6379 redis/redis-stack:latest

在开始之前,让我们创建一个 Go 模块来托管示例:
go mod init go-redis-modules

RedisJSON
在 Redis 中处理 JSON 数据时,传统方法有其局限性。默认情况下,Redis 将值视为简单字符串,缺乏对查询或操作 JSON 等结构化数据的内置支持。因此,开发人员经常将 JSON 存储为 字符串化 值,从而牺牲了对各个字段执行高效操作或利用嵌套结构的能力。这种方法需要解析整个 JSON 文档,即使是微小的更新,导致效率低下并增加处理开销。

RedisJSON 模块通过向 Redis 引入本机 JSON 处理功能来解决这些挑战。它允许您像任何其他本机数据类型一样存储、更新和检索 JSON。

RedisJSON 提供了一组丰富的 JSON 文档操作。以下是一些最常用的命令:

  1. JSON.SET:在 Redis 中设置 JSON 值。
  2. JSON.GET:检索与给定键关联的 JSON 值。
  3. JSON.DEL:从 Redis 中删除 JSON 值。
  4. JSON.TYPE:返回JSON值的类型,指示它是对象、数组、字符串、数字、布尔值还是null。
  5. JSON.ARRAPPEND:将一个或多个值附加到 JSON 数组的末尾。
  6. JSON.ARRLEN:返回 JSON 数组的长度,提供其包含的元素数量。
  7. JSON.OBJKEYS:检索 JSON 对象的键,返回所有存在键的数组。
  8. JSON.OBJLEN:返回JSON对象的大小。
  9. JSON.NUMINCRBY:将 JSON 文档中的数值增加指定的量。
  10. JSON.STRAPPEND:在 JSON 文档中附加字符串。

下面的示例演示了如何在 Go 应用程序中使用各种 RedisJSON 命令。请注意,我们使用的是 go-redis 客户端。

package main

import (
"context"
"errors"
"fmt"
"log"

    "github.com/redis/go-redis/v9"
)

func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})

    ctx := context.Background()

    // JSON.SET
err := rdb.Do(ctx, "JSON.SET", "mydoc", ".", `{"name":"John","credits":30,"cars":["honda","toyota"]}`).Err()
if err != nil {
log.Fatal(err)
}

    // JSON.GET
val, err := rdb.Do(ctx, "JSON.GET", "mydoc").Result()
if err != nil {
log.Fatal(err)
}
fmt.Println("JSON.GET result -", val)

    // JSON.ARRAPPEND
_, err = rdb.Do(ctx, "JSON.ARRAPPEND", "mydoc", ".cars", `"audi"`).Int()
if err != nil {
log.Fatal(err)
}

    fmt.Println("added audi to list of cars using JSON.ARRAPPEND")

    // JSON.GET
val, err = rdb.Do(ctx, "JSON.GET", "mydoc").Result()
if err != nil {
log.Fatal(err)
}
fmt.Println("lastest document", val)

    // JSON.NUMINCRBY
_, err = rdb.Do(ctx, "JSON.NUMINCRBY", "mydoc", ".credits", 5).Result()
if err != nil {
log.Fatal(err)
}
fmt.Println("incremented credits by 5 using JSON.NUMINCRBY")

    // JSON.STRAPPEND
_, err = rdb.Do(ctx, "JSON.STRAPPEND", "mydoc", ".name", `", Jr."`).Int()
if err != nil {
log.Fatal(err)
}
fmt.Println("updated name using JSON.STRAPPEND")

    // JSON.GET
val, err = rdb.Do(ctx, "JSON.GET", "mydoc").Result()
if err != nil {
log.Fatal(err)
}
fmt.Println("latest document", val)

    // JSON.DEL
_, err = rdb.Do(ctx, "JSON.DEL", "mydoc").Int()
if err != nil {
log.Fatal(err)
}
fmt.Println("deleted document using JSON.DEL")

    err = rdb.Do(ctx, "JSON.GET", "mydoc").Err()
if errors.Is(err, redis.Nil) {
fmt.Println("document 'mydoc' could not be found")
}
}

要运行上述代码,请将其复制到名为的文件中 main.go 并执行以下命令:

# get dependencies
go get github.com/redis/go-redis/v9

# run program
go run main.go

请注意,我们不需要获取整个 JSON 文档来更新它。RedisJSON 提供精细操作来处理 JSON 数据,从而提高应用程序性能(减少延迟)并降低成本(减少网络带宽)。

RediSearch
RediSearch模块通过强大的全文搜索功能增强了Redis。它引入了基于倒排索引的搜索引擎,允许高效且可扩展的文本搜索。使用 RediSearch,您可以索引文本数据、执行复杂的搜索查询并检索相关搜索结果。
它提供关键字搜索、精确短语匹配、布尔运算、分页、排序和过滤等功能。
RediSearch 根据搜索结果与查询的匹配程度对搜索结果进行评分,使您能够对搜索结果进行排名和确定优先级。

以下是一些最常用的 RediSearch 命令:

  1. FT.CREATE:使用指定的架构和配置选项创建新的搜索索引。
  2. FT.SEARCH:对指定索引执行搜索查询,根据给定的搜索条件返回匹配的文档。
  3. FT.AGGREGATE:对指定索引进行聚合查询,根据给定的聚合条件返回聚合结果。
  4. FT.INFO:检索有关搜索索引的信息,包括统计信息、配置设置和架构详细信息。
  5. FT.DROPINDEX:删除搜索索引,删除所有文档和关联数据。

下面的示例演示了如何在 Go 应用程序中使用各种 RediSearch 命令。请注意redisearch-go客户端的用法 。

package main

import (
"fmt"
"math/rand"
"strconv"

    "github.com/RediSearch/redisearch-go/redisearch"
"github.com/gomodule/redigo/redis"
)

var pool *redis.Pool
var client *redisearch.Client

var cities = []string{"new york", "london", "paris"}

func init() {
pool = &redis.Pool{Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", "localhost:6379")
}}

    client = redisearch.NewClientFromPool(pool, "user-index")
}

func main() {

    schema := redisearch.NewSchema(redisearch.DefaultOptions).
AddField(redisearch.NewTextFieldOptions("name", redisearch.TextFieldOptions{})).
AddField(redisearch.NewTextFieldOptions("city", redisearch.TextFieldOptions{}))

    indexDefinition := redisearch.NewIndexDefinition().AddPrefix("user:")

    client.CreateIndexWithIndexDefinition(schema, indexDefinition)

    fmt.Println("redisearch index created")

    conn := pool.Get()

    for i := 1; i <= 10; i++ {

        hashName := "user:" + strconv.Itoa(i)
val := redis.Args{hashName}.AddFlat(map[string]string{"user_id": strconv.Itoa(i), "city": cities[rand.Intn(len(cities))]})

        conn.Do("HSET", val...)

        fmt.Println("created hash -", hashName)
}

    docs, total, _ := client.Search(redisearch.NewQuery("*"))

    fmt.Println("no. of indexed documents =", total)

    docs, total, _ = client.Search(redisearch.NewQuery("@city:(paris|london)"))

    fmt.Println("found", total, "users in london or paris")
for _, doc := range docs {
fmt.Println("document ID -", doc.Id)
fmt.Println("document attributes -", doc.Properties)
}

    err := client.DeleteDocument("user:1")
if err != nil {
fmt.Println("failed to delete document (hash) user:1", err)
}
fmt.Println("deleted document (hash) user:1")

    _, total, _ = client.Search(redisearch.NewQuery("*"))

    fmt.Println("no. of indexed documents =", total)

    err = client.DropIndex(true)
if err != nil {
fmt.Println("failed to drop index", err)
}
fmt.Println("dropped index and documents")

    _, total, _ = client.Search(redisearch.NewQuery("*"))

    fmt.Println("no. of indexed documents =", total)
}

要运行上述代码,请将其复制到名为的文件中 main.go 并执行以下命令:

go get github.com/RediSearch/redisearch-go/redisearch
go get github.com/gomodule/redigo/redis

go run main.go

我们使用 Hash 作为文档,但 RediSearch 也可以使用 RedisJSON。当添加或删除文档时,索引会自动更新。本示例演示了一些简单的操作,包括获取所有文档,以及通过城市属性上的 ORclause 进行过滤,以获取居住在 "伦敦 "或 "巴黎 "的用户。

Redis时间序列
在 Redis 中处理大量时间序列数据时,有一些常用的技术。这些涉及将数据存储在 Redis 排序集中,其中分数表示时间戳,成员表示数据值。另一种方法是使用带有时间戳的字符串键作为键名称的一部分。每个键值对代表时间序列中的一个特定数据点。

然而,这些技术在处理大量时间序列数据时存在一些局限性。传统的 Redis 数据结构(如字符串键或排序集)的查询能力有限,并且难以执行复杂的聚合。此外,在处理大型数据集时,将每个数据点存储为单独的键值对可能会消耗大量内存,这通常是时间序列的情况。

RedisTimeSeries模块是原生的时序数据结构,为时序数据提供高效的存储和查询能力。它添加了查询功能,例如检索某个时间范围内的数据、执行聚合(例如求和、计数、平均值)、下采样和插值。它还允许我们定义自动过期或缩减数据采样的保留策略,从而实现高效的数据保留并降低存储要求。RedisTimeSeries 还与生态系统中的其他工具集成,例如 Prometheus 和 Grafana。

RedisTimeSeries 提供了丰富的命令集。以下是一些最常用的:

  1. TS.CREATE:使用指定的键、标签和保留策略创建新的时间序列。
  2. TS.ADD:将新数据点添加到时间序列,并将其与时间戳和值相关联。
  3. TS.RANGE:从指定时间范围内的时间序列中检索一系列数据点。
  4. TS.MRANGE:检索指定时间范围内多个时间序列的数据点。
  5. TS.GET:从时间序列中检索最新的数据点。
  6. TS.MGET:从多个时间序列中检索最新的数据点。
  7. TS.INCRBY:在特定时间戳处增加时间序列中数据点的值。
  8. TS.DECRBY:在特定时间戳处减少时间序列中数据点的值。
  9. TS.INFO:检索有关时间序列的元数据信息,例如样本数量、内存使用情况和保留策略。
  10. TS.QUERYINDEX:对时间序列执行基于索引的查询,根据指定的过滤器和聚合检索数据点。

下面的示例演示了如何在 Go 应用程序中使用各种 RedisTimeSeries 命令。请注意,我们使用的是 redistimeseries-go 客户端。

package main

import (
"fmt"
"log"
"math/rand"
"time"

    redistimeseries "github.com/RedisTimeSeries/redistimeseries-go"
)

const tsName = "temperature:living_room"

func main() {
client := redistimeseries.NewClient("localhost:6379", "", nil)

    // TS.CREATE
err := client.CreateKeyWithOptions(tsName, redistimeseries.DefaultCreateOptions)
if err != nil {
log.Fatal(err)
}

    fmt.Println("created time series key", tsName)

    tempOptions := []float64{24, 24.5, 25}
var storedTS []int64

    for i := 1; i <= 10; i++ {
// TS.ADD
res, err := client.AddAutoTs(tsName, tempOptions[(rand.Intn(len(tempOptions)))])
storedTS = append(storedTS, res)
if err != nil {
log.Fatal(err)
}

time.Sleep(1 * time.Millisecond)
}

    fmt.Println("added time series data")

    // TS.GET
lastDataPoint, err := client.Get(tsName)
if err != nil {
log.Fatal(err)
}
fmt.Printf("lastest data point - timestamp: %v, temp: %v\n", lastDataPoint.Timestamp, lastDataPoint.Value)

    // TS.RANGE
dataPoints, err := client.RangeWithOptions(tsName, storedTS[0], storedTS[len(storedTS)-1], redistimeseries.DefaultRangeOptions)

    if err != nil {
log.Fatal(err)
}

    fmt.Println("TS.RANGE result")

    for _, dp := range dataPoints {
fmt.Printf("timestamp: %v, temp: %v\n", dp.Timestamp, dp.Value)
}
}

要运行上述代码,请将其复制到名为的文件中 main.go 并执行以下命令:

go get github.com/RedisTimeSeries/redistimeseries-go
go run main.go

Redis 模块:最佳实践
本节介绍了一些在这些模块的实际部署中优化可扩展性和性能的最佳实践。

RedisJSON

  • 优化 JSON 结构以实现高效访问:设计 JSON 结构时,请考虑应用程序的访问模式。尽可能展平 JSON 层次结构以避免深层嵌套。这使您可以有效地访问特定字段,而无需获取整个 JSON 文档。使用 RedisJSON 的路径表达式来检索或修改特定的 JSON 元素,而无需解析整个文档。
  • 考虑内存管理和数据大小:RedisJSON 将 JSON 文档存储为 Redis 字符串。请记住,Redis 的最大字符串大小限制为 512 MB。如果您的 JSON 文档很大,请考虑将它们分成更小的部分或使用压缩。
  • 您可以使用 RedisJSON 作为 RedisSearch 的索引:此集成使您能够高效地执行复杂的搜索操作并根据搜索条件检索 JSON 文档。

Redis搜索

  • 仔细选择和优化搜索架构:设计搜索架构时,请考虑应用程序的特定搜索要求。定义需要可搜索的字段并选择适当的字段类型(例如,  text、  numeric、  tag)。仔细分析数据并选择最相关的字段以包含在搜索索引中。避免包含不必要的字段,以最小化索引大小并优化搜索性能。
  • 利用查询优化技术: RedisSearch 提供各种查询优化技术来提高搜索性能。利用查询过滤器来减少搜索空间并根据特定条件缩小结果范围。
  • 此外,请考虑使用词干、同义词和其他特定于语言的分析器来提高搜索准确性。

Redis时间序列

  • 选择最佳时间段:根据数据的频率和粒度选择适当的时间间隔。考虑存储空间和查询性能之间的权衡。较小的存​​储桶提供更详细的数据,但会导致更大的内存使用量。
  • 利用查询优化技术:RedisSearch 提供各种查询优化技术来提高搜索性能。使用查询过滤器来减少搜索空间并缩小结果范围。
  • 使用压缩和下采样:如果您有高频数据且内存资源有限,请考虑启用压缩和下采样配置。这有助于减少内存使用而不影响数据准确性。

https://www.jdon.com/69677.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 设计模式——享元模式

目录 1.概述2.结构3.实现3.1.抽象享元3.2.具体享元3.3.享元工厂3.4.测试 4.优缺点5.使用场景6.JDK 源码解析——Integer 类 1.概述 &#xff08;1&#xff09;享元模式 (Flyweight Pattern) 是一种结构型设计模式&#xff0c;主要通过共享对象来减少系统中的对象数量&#xff…

MUYUCMS v2.1:一款开源、轻量级的内容管理系统基于Thinkphp开发

MuYuCMS&#xff1a;一款基于Thinkphp开发的轻量级开源内容管理系统&#xff0c;为企业、个人站长提供快速建站解决方案。它具有以下的环境要求&#xff1a; 支持系统&#xff1a;Windows/Linux/Mac WEB服务器&#xff1a;Apache/Nginx/ISS PHP版本&#xff1a;php > 5.6 (…

达梦数据库答案

1、 创建数据库实例&#xff0c;到/dm8/data下&#xff0c;数据库名&#xff1a;DEMO&#xff0c;实例名DEMOSERVER&#xff08;10分&#xff09; [dmdbadmServer ~]$ cd /dm8/tool [dmdbadmServer tool]$ ./dbca.sh1、 簇大小32&#xff0c;页大小16&#xff0c;登录密码&…

挑战100天 AI In LeetCode Day08(热题+面试经典150题)

挑战100天 AI In LeetCode Day08&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-102.1 题目2.2 题解 三、面试经典 150 题-103.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…

tcpdump抓包的字节数量与ethtool统计数据不同的原因

情况介绍 在进行RDMA抓包流量分析时&#xff0c;我使用ethtool工具统计了RDMA网卡的流量发送数据数量&#xff0c;然后使用tcpdump进行抓包。 经过分析发现&#xff0c;tcpdump得到的数据数量总是大于ethtool得到的数据数量&#xff0c;而且每个数据包会多出4个字节。 分析 …

eclipse安装lombok插件

lombok插件下载:Download 下载完成&#xff0c;lombok.jar放到eclipse根目录&#xff0c;双击jar运行 运行界面&#xff0c;点击Install安装。 安装完成&#xff0c;重启IDE&#xff0c;rebuild 项目。 rebuild 项目

【分享】Excel“只读方式”的两种模式

查阅Excel表格的时候&#xff0c;担心不小心修改了内容&#xff0c;可以给Excel设置以“只读方式”打开&#xff0c;这样就算修改了内容也不能直接保存表格。Excel表格可以设置两种“只读方式”&#xff0c;一起来看看吧&#xff01; “只读方式” 1&#xff1a; 打开Excel表…

cgo与调用c的回调函数指针

cgo直接调用函数&#xff0c;使用基本数据类型非常简单&#xff0c;包括一些结构体也比较简单&#xff0c;嵌套的稍微复杂些&#xff0c;但也可以&#xff0c;但有的时候&#xff0c;cgo调用c函数&#xff0c;会需要传递一个回调函数的指针&#xff0c;这时候就比较复杂了&…

基于PHP的设云尘资讯网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。你想解决的问题&#xff0c;今天给大家介绍…

iOS应用签名的步骤有哪些?

用电脑给iOS应用签名的步骤如下&#xff1a; 获取开发者证书。通过Apple开发者中心申请开发者账号&#xff0c;并生成相应的开发者证书。根据需求&#xff0c;选择免费的个人开发者账号或付费的企业开发者账号。创建App ID。在签名之前&#xff0c;需要创建一个唯一的App ID。…

工作记录--(用HTTPS,为啥能被查出浏览记录?如何解决?)---每天学习多一点

由于网络通信有很多层&#xff0c;即使加密通信&#xff0c;仍有很多途径暴露你的访问地址&#xff0c;比如&#xff1a; DNS查询&#xff1a;通常DNS查询是不会加密的&#xff0c;所以&#xff0c;能看到你DNS查询的观察者&#xff08;比如运营商&#xff09;是可以推断出访问…

平安人寿基于 Apache Doris 统一 OLAP 技术栈实践

导读&#xff1a;平安人寿作为保险行业领军企业&#xff0c;坚持技术创新&#xff0c;以数据业务双轮驱动的理念和更加开放的思路来应对不断增长的数据分析和应用需求&#xff1b;以深挖数据价值、保障业务用数效率为目标持续升级大数据产品体系。自 2022 年起平安人寿开始引入…

初始MySQL(五)(自我复制数据,合并查询,外连接,MySQL约束:主键,not null,unique,foreign key)

目录 表复制 自我复制数据(蠕虫复制) 合并查询 union all(不会去重) union(会自动去重) MySQL表的外连接 左连接 右连接 MySQL的约束 主键 not null unique(唯一) foreign key(外键) 表复制 自我复制数据(蠕虫复制) #为了对某个sql语句进行效率测试,我们需要海量…

No195.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

DOS编程基础总结

文章目录 一、概念1.1 DOS命令---windows支持的命令行指令1.2 BAT脚本---DOS批处理脚本1.3 DOS命令帮助---help / help command 二、基础语法2.1 变量&#xff08;读/写/查看/关键环境变量&#xff09;2.2 if条件语句2.3 for循环语句2.4 注释--- 行首:: 或者 行首REM&#xff0…

odoo16前端框架源码阅读——boot.js

odoo16前端框架源码阅读——boot.js 从名字就能看出来&#xff0c;这个文件是一个启动文件。 odoo前端将所有的js打包成了两个文件&#xff0c;一个是common.js,另一个是backend.js, 而common.js 是最先加载的 在common.js打包的js文件中最先加载的是下面的文件&#xff0c;看…

【华为OD题库-007】代表团坐车-Java

题目 某组织举行会议&#xff0c;来了多个代表团同时到达&#xff0c;接待处只有一辆汽车&#xff0c;可以同时接待多个代表团&#xff0c;为了提高车辆利用率&#xff0c;请帮接待员计算可以坐满车的接待方案&#xff0c;输出方案数量。 约束: 1.一个团只能上一辆车&#xff0…

监控和数据采集软件架构和详细设计

介绍 监控和数据采集软件通过提供实时监控、数据收集和分析功能&#xff0c;在各个行业中发挥着至关重要的作用。这些软件应用程序可帮助企业收集有价值的见解、优化流程并做出明智的决策。在本文中&#xff0c;我们将探讨监测和数据采集软件的软件架构、编程技术和详细设计规范…

【STM32 CAN】STM32G47x 单片机FDCAN作为普通CAN外设使用教程

STM32G47x 单片机FDCAN作为普通CAN外设使用教程 控制器局域网总线&#xff08;CAN&#xff0c;Controller Area Network&#xff09;是一种用于实时应用的串行通讯协议总线&#xff0c;它可以使用双绞线来传输信号&#xff0c;是世界上应用最广泛的现场总线之一。CAN协议用于汽…

拓扑排序软件设计——ToplogicalSort_app(含有源码、需求分析、可行性分析、概要设计、用户使用手册)

拓扑排序软件设计 前言1. 需求分析2. 可行性分析2.1 简介2.2 技术可行性分析2.2.1 技术实现方案2.2.2 开发人员技能要求2.2.3 可行性 2.3 操作可行性分析2.4 结论 3. 项目报告3.1 修订历史记录3.2 软硬件环境3.3 需求分析3.4 详细设计3.4.1 类设计3.4.2 核心流程描述3.4.3 核心…