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.hqwc.cn/news/162351.html

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

相关文章

微服务架构——笔记(3)Eureka

微服务架构——笔记(3) 基于分布式的微服务架构 本次笔记为 此次项目的记录,便于整理思路,仅供参考,笔者也将会让程序更加完善 内容包括:1.支付模块、2.消费者订单模块、支付微服务入驻Eureka、Eureka集群…

基于单片机的商场防盗防火系统设计

收藏和点赞,您的关注是我创作的动力 文章目录 概要 一、系统分析二、系统总设计2.1基于单片机的商场防火防盗系统的总体功能2.2系统的组成 三 软件设计4.1软件设计思路4.2软件的实现4.2.1主控模块实物 四、 结论五、 文章目录 概要 本课题设计一种商场防火防盗报警…

Win10 + VS017 编译SQLite3.12.2源码

参考: [1] WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 [2] 如何编译SQLite-How To Compile SQLite-CSDN博客 如何生成静态库: 参考: WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 如何生成exe:…

3D高斯泼溅(Splatting)简明教程

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D场景编辑器 3D 高斯泼溅(Splatting)是用于实时辐射场渲染的 3D 高斯分布描述的一种光栅化技术,它允许实时渲染从小图像样…

15种稳定扩散模型的技术示例

推荐Stable Diffusion自动纹理工具: DreamTexture.js自动纹理化开发包 什么是稳定扩散模型? 潜在扩散模型 (LDM) 是一种图像生成技术,其工作原理是在潜在表示空间中迭代“去噪”数据,然后将表示解码为完整…

Android Framework学习之Activity启动原理

Android Activity启动原理 Android 13.0 Activity启动原理逻辑流程图如下:

【Agent模型1】MemGPT: Towards LLMs as Operating Systems

论文标题:MemGPT: Towards LLMs as Operating Systems 论文作者:Charles Packer, Vivian Fang, Shishir G. Patil, Kevin Lin, Sarah Wooders, Joseph E. Gonzalez (UC Berkeley) 论文原文:https://arxiv.org/abs/2310.08560 论文出处&#x…

【入门Flink】- 04Flink部署模式和运行模式【偏概念】

部署模式 在一些应用场景中,对于集群资源分配和占用的方式,可能会有特定的需求。Flink为各种场景提供了不同的部署模式,主要有以下三种:会话模式(Session Mode)、单作业模式(Per-Job Mode&…

程序员笔记本电脑选 windows 还是 MAC

计算机选择是每个进入 IT 行业同学的第一个重要选择,那么你是怎么选择的呢? 选择操作系统(Windows还是macOS)取决于程序员的需求、偏好和工作流程。每个操作系统都有其优点和缺点,下面将分别讨论它们,以帮助…

Amazon EC2 安全可调用的云虚拟主机服务器

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Amazon EC2 打造全新的科技链 Amazon Elastic Compute Cloud(Amazon EC2)提供最广泛、最深入的计算平台,拥有超过 500 个实例&…

使用WMS仓储管理系统防止呆料的几个建议

随着互联网的深入,客户的需求变化迅速,从淘宝、京东到直播带货,产品的更新迭代速度越来越快。对于制造企业而言,如何在这样的环境中降低呆腐物料,提高利润,是其生存和发展的关键。 面对快速迭代的产品&…

Go invalid memory address or nil pointer dereference错误 空指针问题

Go 指针声明后赋值,出现 panic: runtime error: invalid memory address or nil pointer dereference,这种是内存地址错误。 首先我们要了解指针,指针地址在 Go 中 * 代表取指针地址中存的值,& 代表取一个值的地址对于指针&am…