golang工程中间件——redis常用结构及应用(string, hash, list)

Redis

命令中心

【golang工程中间件——redisxxxxx】这些篇文章专门以应用为主,原理性的后续博主复习到的时候再详细阐述

string结构以及应用

字符数组,redis字符串是二进制安全字符串,可以存储图片等二进制数据,同时也可以存储经过 messagepack 或者 protobuffer 等工具压缩后的二进制数据; 内部实际存储根据 string 的数据特征可采用 int 、 embstr 、 raw 存储;(长度,是否能化为整数等条件,主要是长度)

基础命令

# 设置 key 的 value 值
SET key val
# 获取 key 的 value
GET key
# 执行原子加一的操作
INCR key
# 执行原子加一个整数的操作
INCRBY key increment
# 执行原子减一的操作
DECR key
# 执行原子减一个整数的操作
DECRBY key decrement
# 如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做
SETNX key value
# 删除 key val 键值对
DEL key
# 设置或者清空key的value(字符串)在offset处的bit值。
SETBIT key offset value
# 返回key对应的string在offset处的bit值
GETBIT key offset
# 统计字符串被设置为1的bit数.
BITCOUNT key

应用

对象存储

常用存储json字符串,或者protobuffer序列化二进制。

SET role:10001 '{["name"]:"mark",["sex"]:"male",["age"]:30}'
GET role:10001
# 固定不变或者几乎不会修改它采用

程序读取后反序列化为对象即可

累加器
# 统计访问数 累计加1
incr accessCount
# 累计加100
incrby accessCount 100
分布式锁

在这里插入图片描述

  • 排他性
  • 定义获取锁行为
  • 定义释放锁行为
# 加锁
setnx lock 1
# 释放锁
del lock
位运算
# 月签到功能 10001 用户id 202107 2021年7月份的签到 7月份的第1天
setbit sign:10001:202107 1 1
# 计算 2021年7月份 的签到情况
bitcount sign:10001:202107
# 获取 2021年7月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202107 2

list结构以及应用

首尾相接的双向链表,链表首尾操作时间复杂度为O(1) ;查找中间元素时间复杂度为O(n) ;

列表中数据可能会被压缩:

  • 元素长度小于 48,不压缩;
  • 元素压缩前后长度差不超过 8,不压缩;

基础命令

# 从队列的左侧入队一个或多个元素
LPUSH key value [value ...]
# 从队列的左侧弹出一个元素
LPOP key
# 从队列的右侧入队一个或多个元素
RPUSH key value [value ...]
# 从队列的右侧弹出一个元素
RPOP key
# 返回从队列的 start 和 end 之间的元素 0, 1 2
LRANGE key start end
# 从存于 key 的列表里移除前 count 次出现的值为 value 的元素
LREM key count value
# 它是 RPOP 的阻塞版本,因为这个命令会在给定list无法弹出任何元素的时候阻塞连接
# block right pop
BRPOP key timeout #

应用

LPUSH + LPOP
# 或者
RPUSH + RPOP

队列
LPUSH + RPOP
# 或者
RPUSH + LPOP
异步队列

在这里插入图片描述

redis队列存储应用日志,再落盘到ES索引中

类似异步队列,一些后台服务往redis队列里写日志,专门起日志落盘程序,读取redis队列中的日志json字符串(对象),格式化落盘到ES索引中。

阻塞队列(blocking queue)
LPUSH + BRPOP
# 或者
RPUSH + BLPOP

实际应用过程中,需要保证命令的原子性,所以需要使用 lua 脚本或者使用 pipeline 命令 + 事 务;

# 在某些业务场景下,需要获取固定数量的记录;比如获取最近50条战绩;这些记录需要按照插入的先
后顺序返回;
lpush says '{["name"]:"狐金道长", ["text"]:"镇山河!",
["picture"]:["url://image-20230601232741434.jpg", "url://image202306asxx741435.jpg"], timestamp = 1699241288}'
lpush says '{["name"]:"六红军爷", ["text"]:"任驰骋!",
["picture"]:["url://image-20230601134742434.jpg", "url://image20230asff72741436.jpg"], timestamp = 1699241288}'
lpush says '{["name"]:"蹩脚毒萝", ["text"]:"化蝶!",
["picture"]:["url://image-20230601172543434.jpg", "url://image2021060123a41437.jpg"], timestamp = 1699241288}'
lpush says '{["name"]:"sb弓", ["text"]:"我是傻狗",
["picture"]:["url://image-20230601172744678.jpg", "url://image20230601146272741438.jpg"], timestamp = 1699241288}'
# 裁剪最近5条记录 例如聊天记录 
ltrim says 0 4
# 获取队列所有内容
lrange says 0 -1

问题

可能会有很多连接去对list进行操作。但是redis是单线程的,只会处理一个命令。但是在这两条命令之间,可能会有别的命令对list进行操作。所以需要保证这两个命令一起执行。

# 裁剪最近5条记录 例如聊天记录 
ltrim says 0 4
# 获取队列所有内容
lrange says 0 -1

实际应用过程中,需要保证命令的原子性,所以需要使用 lua 脚本或者使用 pipeline 命令 + 事 务

hash结构以及应用

字典结构,通过 hash 函数来确定节点的位置,很多高级语言包含 这个数据结构,例如 c++ 中 unordered_map,go 语言当中的 map 结构;

基础命令

# 获取 key 对应 hash 中的 field 对应的值
HGET key field
# 设置 key 对应 hash 中的 field 对应的值
HSET key field value
# 设置多个hash键值对
HMSET key field1 value1 field2 value2 ... fieldn valuen
# 获取多个field的值
HMGET key field1 field2 ... fieldn
# 给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
# 获取 key 对应的 hash 有多少个键值对
HLEN key
# 删除 key 对应的 hash 的键值对,该键为field
HDEL key field

存储结构

当节点数量少的时候且字符串长度小的时候,内部采用压缩列表存储,否则采用字典实现;

10.62.122.23:7002> object encoding MyCart:10001
"ziplist"

应用

存储对象
hmset hash:10001 name qudaodao age 18 sex male
# 与 string 比较
set hash:10001 '{["name"]:"qudaodao",["sex"]:"male",["age"]:18,
["money"]:1000000}'
# 假设现在修改qudaodao的年龄为19岁
# hash:
hset hash:10001 age 19
# string:
get role:10001
# 将得到的字符串调用json.decode解密,取出字段,修改 age 值
# 再调用json加密
set role:10001 '{["name"]:"qudaodao",["sex"]:"male",["age"]:19}'
购物车
# 将用户id作为 key
# 商品id作为 field
# 商品数量作为 value
# 注意:这些物品是按照我们添加顺序来显示的;
# 添加商品:
hset MyCart:10001 40001 1
lpush MyItem:10001 40001
# 增加数量:
hincrby MyCart:10001 40001 1
hincrby MyCart:10001 40001 -1 // 减少数量1
# 显示所有物品数量:
hlen MyCart:10001
# 删除商品:
hdel MyCart:10001 40001
lrem MyItem:10001 1 40001
# 获取所有物品:
lrange MyItem:10001
# 40001 40002 40003
hget MyCart:10001 40001
hget MyCart:10001 40002
hget MyCart:10001 40003

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

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

相关文章

Spark 新特性+核心回顾

Spark 新特性核心 本文来自 B站 黑马程序员 - Spark教程 :原地址 1. 掌握Spark的Shuffle流程 1.1 Spark Shuffle Map和Reduce 在Shuffle过程中,提供数据的称之为Map端(Shuffle Write)接收数据的称之为Reduce端(Sh…

10 索引优化与查询优化

文章目录 索引失效案例关联查询优化对于左外连接对于内连接JOIN语句原理简单嵌套循环连接SNLJ索引嵌套循环连接INLJ块嵌套循环连接BNLJHash Join 子查询优化排序优化filesort算法:双路排序和单路排序 分组优化分页优化优先考虑覆盖索引索引下推ICP使用条件 其他查询…

Python语言高级实战-内置函数super()的使用之类的多继承(附源码和实现效果)

实现功能 super()函数的调用顺序是按照方法解析顺序(Method Resolution Order, MRO)来确定的。MRO 是一个确定继承顺序的算法,它使用 C3 线性化算法来避免潜在的方法冲突。Python会根据继承顺序自动计算 MRO,我们只需要使用 supe…

c语言从入门到实战——操作符详解

操作符详解 前言1. 操作符的分类2. 二进制和进制转换2.1 2进制转10进制2.1.1 10进制转2进制数字 2.2 2进制转8进制和16进制2.2.1 2进制转8进制2.2.2 2进制转16进制 3. 原码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符:&、|、^、~6. 单目…

力扣 138. 随机链表的复制

题目描述: 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的…

伦敦金开户需要多少资金,有开户条件吗?

伦敦金(London Gold)是黄金市场中备受瞩目的投资种类之一,无论是专业投资者还是新手,都对伦敦金感兴趣。但关于开户需要多少资金,以及是否有特定的开户条件,这些问题可能会让一些新手投资者感到困惑。 首先…

GPT-4V:AI在医疗领域的应用

OpenAI最新发布的GPT-4V模型为ChatGPT增添了语音和图像功能,为用户提供了更多在日常生活中使用ChatGPT的方式。这次更新将为用户带来更加便捷、直观的交互体验,用户可以直接通过拍照上传图片,并提出相关问题。OpenAI的最终目标是构建一个安全…

云服务器哪家便宜靠谱 | 简单了解亚马逊云科技发展史

云服务器哪家便宜又靠谱呢?为什么说亚马逊云科技在这道题答案的第一行,一篇故事告诉你。 1994年,杰夫贝索斯在西雅图创建了亚马逊,最初只是一个在线书店。 1997年,亚马逊在纳斯达克交易所上市,成为一家公…

大模型的实践应用5-百川大模型(Baichuan-13B)的模型搭建与模型代码详细介绍,以及快速使用方法

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用5-百川大模型(Baichuan-13B)的模型搭建与模型代码详细介绍,以及快速使用方法。 Baichuan-13B 是由百川智能继 Baichuan-7B 之后开发的包含 130 亿参数的开源可商用的大规模语言模型,在权威的中文和英文 benchmark 上均…

SVG循环滑动效果

1.循环滑动图&#xff08;4张) 效果图 svg滑块视频 代码&#xff1a;&#xff08;如果要调整整体的速度和时间请对begin“1s” dur"12s"属性进行编辑&#xff09; <section style"margin: 0px auto;display: block;width: 100%;" data-mpa-powered-by…

一文深入搞懂ARM处理器架构

1、嵌入式处理器基础 典型的微处理器由控制单元、程序计数器&#xff08;PC&#xff09;、指令寄存器&#xff08;IR&#xff09;、数据通道、存储器等组成 。 指令执行过程一般分为&#xff1a; 取指&#xff1a; 从存储器中获得下一条执行的指令读入指令寄存器&#xff1…

PTA 编程题(C语言)-- 连续因子

题目标题&#xff1a; 连续因子 题目作者 陈越 浙江大学 一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3567&#xff0c;其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N&#xff0c;要求编写程序求出最长连续因子的个数&#xff0c…

JavaEE的渊源

JavaEE的渊源 1. JavaEE的起源2. JavaEE与Spring的诞生3. JavaEE发展历程&#xff08;2003-2007&#xff09;4. JavaEE发展历程&#xff08;2009-至今&#xff09;5. Java的Spec数目与网络结构 1. JavaEE的起源 我们首先来讲一下JavaEE的起源 ,为什么要来讲起源 &#xff1f; …

良品铺子、三只松鼠、来伊份双11内卷!谁是“新王”?

今年双11&#xff0c;三只松鼠(300783.SZ)&#xff0c;良品铺子(603719.SH)和来伊份(603777.SH)的休闲零食产品在各大电商平台火热营销&#xff1b;营销热业绩冷&#xff0c;其三季报均不理想。 「不二研究」据其三季报发现&#xff1a;今年前三季度&#xff0c;良品铺子、三只…

如何给WSL2缩减硬盘(即减小虚拟大小)?

如何给WSL2缩减硬盘&#xff08;即减小虚拟大小&#xff09;&#xff1f; 1.软件环境⚙️&#x1f50d;2.问题描述&#x1f50d;&#x1f421;3.解决方法&#x1f421;&#x1f914;4.结果预览&#x1f914; 1.软件环境⚙️ Windows10 教育版64位 WSL 2 Ubuntu 20.04 &#x1f…

微信小程序之自定义组件开发

1、前言 从小程序基础库版本 1.6.3 开始&#xff0c;小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。开发者可以将页面内的功能模块抽象成自定义组件&#xff0c;以便在不同的页面中重复使用&#xff1b;也可以将复杂的页面拆分成多个低耦…

泛微OA_lang2sql 任意文件上传漏洞复现

简介 泛微OA E-mobile系统 lang2sql接口存在任意文件上传漏洞&#xff0c;由于后端源码中没有对文件没有校验&#xff0c;导致任意文件上传。攻击者可利用该参数构造恶意数据包进行上传漏洞攻击。 漏洞复现 FOFA语法&#xff1a; title"移动管理平台-企业管理" 页…

【Mybatis】3 的操作类型对象

前言知识汇总 上篇文章中我们已经详细介绍了Mybatis的存储类对象。我们上篇提到了&#xff1a; Mapper.xml当中的SQL标签都被解析成了一个一个的MappedStatement对象。那么我们当中的SQL是基于什么形式进行封装的呢&#xff1f; 我们要知道&#xff0c;Java当中一切皆对象。M…

人人都会的 Blazor —— 1.3 项目结构

项目结构 使用 Visual Studio 2022 创建 Blazor 项目。 在搜索框中输入【blazor】关键字,将列出以下已经存在的项目模板: Blazor Server App:基于 Blazor Server 托管模型的项目,并建立一些示例代码和组件;Blazor WebAssembly App:基于 Blazor WebAssembly 托管模型的项…

优维低代码实践:打包发布

导语 优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。…
最新文章