Redis数据结构与连接

server/2024/11/15 6:15:38/

1 基本的数据结构

1.1 string

string的实现有多种

  • int:字符串长度小于等于20且能转成整数
  • raw:字符串长度大于44
  • embstr:字符串长度小于等于44

字符串长度小于1M 时,加倍扩容;超过 1M 每次只多扩1M;字符串最大长度为 512M

string是二进制安全字符串,可以存储图片,二进制协议等二进制数据

基本命令:

  • SET key val
  • GET key
  • INCR key
  • INCRBY key increment
  • DECR key
  • DECRBY key decrement
  • SETNX key value(set not exist)
  • DEL key
  • SETBIT key offset value
  • GETBIT key offset
  • BITCOUNT key
# 月签到功能 2021年6月份的第1天
setbit sign:10001:202106 1 1
# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106
# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2

1.2 list

  • 双向链表实现,列表首尾操作(删除和增加)时间复杂度 O(1) ;查找中间元素时间复杂度为O(n)

基本命令:

  • LPUSH key value [value …]
  • LPOP key
  • RPUSH key value [value …]
  • RPOP key
  • LRANGE key start end
  • LREM key count value 移除前 count 次出现的值为 value 的元素
  • BRPOP key timeout RPOP 的阻塞版本,这个命令会在给定list无法弹出任何元素的时候阻塞连接
  • LTRIM key start stop

实际项目中需要保证命令的原子性,所以一般用 lua 脚本 或者使用 pipeline 命令

存储结构:

  • quicklist(双向链表)
  • ziplist(压缩列表)

1.3 hash

散列表

基本命令

  • HGET key field
  • HSET key field value
  • HMSET key field1 value1 field2 value2 … fieldn valuen
  • HMGET key field1 field2 … fieldn
  • HGETALL key
  • HINCRBY key field increment
  • HLEN key
  • HDEL key field

存储结构:

  • 节点数量大于 512(hash-max-ziplist-entries) 或所有字符串长度大于 64(hash-max-ziplist-value),则使用 dict 实现
  • 节点数量小于等于 512 且有一个字符串长度小于 64,则使用 ziplist 实现

1.4 set

基本命令

  • SADD key member [member …]
  • SCARD key
    • Get the number of members in a set
  • SMEMBERS key
  • SISMEMBER key member
  • SRANDMEMBER key [count]
  • SPOP key [count]
  • SDIFF key [key …] 差集
  • SINTER key [key …] 交集
  • SUNION key [key …] 并集

存储结构:

  • 元素都为整数且节点数量小于等于 512(set-max-intset-entries),则使用整数数组存储
  • 元素当中有一个不是整数或者节点数量大于 512,则使用字典存储

1.5 zset

有序集合

基本命令:

  • ZADD key [NX|XX] [CH] [INCR] score member [score member …]
  • ZREM key member [member …]
  • ZSCORE key member
  • ZINCRBY key increment member
  • ZCARD key
  • ZRANK key member 返回有序集key中成员member的排名
  • ZRANGE key start stop [WITHSCORES]
  • ZREVRANGE key start stop [WITHSCORES]

存储结构:

  • 节点数量大于 128 或者有一个字符串长度大于 64,则使用跳表(skiplist)
  • 节点数量小于等于 128(zset-max-ziplist-entries)且所有字符串长度小于等于 64(zset-max-ziplist-value),则使用 ziplist 存储

redis_pipeline_109">2 redis pipeline

redis pipeline 是一个客户端提供的机制,而不是服务端提供的

在这里插入图片描述

可以一次性发多条指令,减少网络交互

redis_117">3 redis事务

  • MULTI 开启事务,事务执行过程中,单个命令是入队列操作,直到调用 EXEC 才会一起执行

  • 乐观锁实现,所以失败需要重试

相关指令:

  • MULTI 开启事务
  • EXEC 提交事务
  • DISCARD 取消事务
  • WATCH 检测 key 的变动,若在事务执行中,key 变动则取消事务

4 lua脚本

实际使用,并不是使用MULTI等命令,而是使用lua脚本实现原子性。

Redis中内嵌一个lua虚拟机,用来执行Redis lua 脚本,Redis lua脚本可以执行多个命令,并保证原子性

127.0.0.1:6379> set lua_test 100
OK
127.0.0.1:6379> eval 'local key = KEYS[1]; local val = redis.call("get", key); redis.call("set", key, 2*val); return 2*val;' 1 lua_test
(integer) 200

语法:

EVAL script numkeys key [key ...] arg [arg ...]

可通过script load获取lua脚本的hash字符串

127.0.0.1:6379> SCRIPT LOAD 'local key = KEYS[1]; local val = redis.call("get", key); redis.call("set", key, 2*val); return 2*val;'
"5640042b18b79e5405b722cf97c15d87768a3ce9"
127.0.0.1:6379> SCRIPT EXISTS "5640042b18b79e5405b722cf97c15d87768a3ce9"
1) (integer) 1

使用EVALSHA执行

EVALSHA sha1 numkeys key [key ...] arg [arg ...]
127.0.0.1:6379> EVALSHA 5640042b18b79e5405b722cf97c15d87768a3ce9 1 lua_test
(integer) 400

实际应用中,会在服务器启动时,将所有的lua脚本先获取到对应的哈希值,然后存在一个unordered_map中,这样后序可直接使用EVALSHA执行

# 清除所有脚本缓存
> script flush
OK
# 如果当前脚本运行时间过长(死循环),可以通过 script kill 杀死当前运行的脚本
> script kill

5 ACID特性

A(atomic):原子性,事务中的多个操作要么都成功,要么都失败。

  • redis不支持回滚,即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。

C(consistent):一致性

  • Redis满足数据库层面的一致性,即对于string类型,不能使用lpush操作
  • Redis不满足逻辑上的一致性,对于lua脚本,假如有多条指令,分别是A、B、C、D,若B指令出错,后面的指令都不会执行,但A指令仍然生效。
    • 一个扣钱一个加钱;可能出现扣钱执行错误,加钱执行正确,那么最终还是会加钱成功;系统凭空多了钱

I(isolation):隔离性

  • redis 是单线程执行,天然具备隔离性

D(duration):持久性

  • redis 只有在 aof 持久化策略的时候,并且需要在 redis.conf 中appendfsync=always 才具备持久性;实际项目中几乎不会使用 aof 持久化策略

lua 脚本满足原子性和隔离性;一致性和持久性不满足

6 Redis同步连接

hiredis已封装了相关的接口

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>int main() {unsigned int j, isunix = 0;redisContext *c;redisReply *reply;const char *hostname = "127.0.0.1";int port = 6379;struct timeval timeout = { 1, 500000 }; // 1.5 secondsc = redisConnectWithTimeout(hostname, port, timeout);if (c == NULL || c->err) {if (c) {printf("Connection error: %s\n", c->errstr);redisFree(c);} else {printf("Connection error: can't allocate redis context\n");}exit(1);}int roleid = 10001;reply = redisCommand(c, "hgetall role:%d", roleid);if (reply->type != REDIS_REPLY_ARRAY) {printf("reply error: %s\n", reply->str);} else {printf("reply:number of elements=%lu\n", reply->elements);for (size_t i = 0; i < reply->elements; i++) {printf("\t %lu : %s\n", i, reply->element[i]->str);}}freeReplyObject(reply);/* Disconnects and frees the context */redisFree(c);return 0;
}

编译

$ gcc test.c -o test -lhiredis

7 Redis异步连接

hiredis提供了适配reactor网络模型的异步驱动方式(adapters文件夹)。

在这里插入图片描述

libevent.h中

在这里插入图片描述

可以看到有addRead(注册读事件)、delRead(注销读事件)、addWrite(注册写事件)、delWrite(注销写事件)

可替换成自己设计的接口。

参考链接:https://xxetb.xetslk.com/s/1QH6AQ


http://www.ppmy.cn/server/111930.html

相关文章

gitignore does not work

在.gitignore文件中新增想要ignore的文件路径&#xff0c;但是不生效。 这是由于git cache导致的&#xff0c;处理方法见下方链接&#xff1a; caching - Ignore files that have already been committed to a Git repository - Stack Overflow

Linux 进程概念 进程状态 fock函数讲解

PID和PPID 我如果想获取自己的PID呢&#xff1f; pid_t getpid(void);头文件:#include<sys/types.h> #include<unistd.h> 返回调用这个函数的进程ID(自己的PID) PID一般会变化 如何获取PPID? pid_t getppid(void);(父ID)头文件:#include<sys/types.h>…

微服务CI/CD实践(二)服务器先决软件安装

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决软件安装 微服务CI/CD实践&#xff08;三&#xff09;gitlab部署 微服务CI/CD实践&#xff08;四&#xff09;nexus3部…

upload文件上传靶场

第一关 修改网页源代码为php文件&#xff0c;上传一个php文件查看 第二关 上传一个php文件查看&#xff0c;发现不能上传 将php文件改为jpg格式上传抓包查看,将jpg改为php放行 第三关 上传一个php文件查看 将php改为php3格式上传查看 第四关 创建一个.htaccess文件先上传在…

FIFO求和实验

前言 FIFO&#xff08;先进先出&#xff09;队列在图像处理中的应用非常广泛&#xff0c;特别是在需要处理实时数据流和保证数据顺序的场景中。以下是一些具体应用实例&#xff1a;在实时视频流处理中&#xff0c;FIFO队列用于缓存图像帧。这样可以确保图像数据按照捕获顺序被处…

K8S CronJob

K8S 知识目录 Kubernetes (K8s) 中的 CronJob 是一种特殊的作业&#xff08;Job&#xff09;&#xff0c;它允许根据给定的时间表&#xff08;cron 格式&#xff09;来运行作业。这对于需要定期执行的任务&#xff08;如数据库备份、日志清理、发送报告等&#xff09;非常有用…

软考攻略/超详细/系统集成项目管理工程师/基础知识分享05

2.1.3 存储与数据库&#xff08;掌握&#xff09; 1、存储技术 存储分类根据服务器类型分为&#xff1a;封闭系统的存储和开放系统的存储 封闭系统主要指大型机等服务器&#xff1b;开放系统指基于包括麒麟、欧拉、UNIX、Linux等操作系统的服务器 开放存储的系统分为&#xff…

C# 窗口页面布局

1.Groupbox 单机鼠标右键&#xff0c;置于底层 2.Label 在右方属性中修改名称 3.ComboBox 点击属性中的集合&#xff0c;可以添加选择项 4.CheckBox 在属性中修改名称 5.RichTextBox 富文本 在属性中修改名称与区域 6.StatusStrip 状态栏 将AutoSize改成false就可以修改…