当前位置: 首页 > news >正文

Redis相关命令详解及其原理

Redis概念

Redis,英文全称是remote dictionary service,也就是远程字典服务。这是kv存储数据库。Redis,包括所有的数据库,都是请求-回应模式,通俗来说就是数据库不会主动地要给前台推送数据,只有前台发送了申请才能数据才能响应从而相应并且发送出数据。

为什么会有redis?在分布式场景中,不同的节点可能之间经常会共享某些数据,因此我们可以把这些共享数据存放在redis当中,哪些节点需要就可以去redis当中提取数据。

Redis的特点

  1. kv-存储。所有的数据都是以键值对的方式存在的,当然这个“值”也有可能是键值对。
  2. 内存数据库。redis所有的数据都存储在内存中,可以快速地响应请求。关系型数据库的数据一般大部分都是放在磁盘中,其中一部分放在内存中可以提升取数据的速度。Redis不是关系型数据库。
  3. 数据结构数据库。体现在redis的kv存储,v支持丰富的数据类型,最常用的有五种数据结构:stirng字节串(能存储二进制数据和字符串),list链表,hash,zset有序集合(能有序尽量有序),set无序集合,以及stream消息队列(很少使用,用的话一般用kafka),hyperloglog(很少使用)。

不同的数据结构会对应不同的命令。Value的类型由第一次涉及到它的命令的类型决定。

图解redis

Redis的kv关系直观图

如图,value为list的时候是双向循环链表,value为hash 的时候是个kv形式的hash表。value为zset的时候,给每个m元素都搭配一个c(score),通过对score的排序实现有序。

所有的key都是string(字节串),因为支持存储二进制数据。

Redis的安装与启动教程

安装

进入redis官网下载redis

本文中选择下载6.2版本的redis

下载好了之后解压缩成一个文件夹。

cd redis-6.2

su

make

make test

make install

安装好了之后,/usr/local/bin下会看到redis-server和redis-cli,分别对应了redis的服务器和客户端。

启动

创建一个新文件夹:mkdir redis-data

将redis-6.2文件夹下的redis.conf文件移动到redis-data下,

修改redis.conf文件,吧requirepass和daemonize属性,修改如下的白字部分:

修改好了之后,redis服务器启动命令如下:

查询redis服务器是否启动成功:

用redis-cli连接到redis-server:

之后的redis命令都在redis-cli上操作。

redis-cli案例

设置并获取string的kv存储

设置并获取list的kv存储

设置并获取hash的kv存储。

设置并获取set的kv存储

设置并获取zset的kv存储

Redis存储结构

Redis的底层数据结构是散列表。什么是散列表?简单来说散列表是一系列的链表,redis的这些链表的一个节点一对kv键值对,同时这些链表的头节点指针分别放在了同一个数组的不同位置,被串起来了。

当有一个新的键值对产生需要存储进入redis的时候,redis先先对这个key做一个hash和取余,看看要把这个键值对放在散列表的第几个链表中,然后顺着数组找到这个链表的头节点,把它插入到这个链表中。

下图中是一个redis存储结构的概念图,部分value用了一些冷门数据结构,不必太在意。跳表是用来实现zset存储的,整型数组是用来实现set存储的,动态字符串是用来实现string存储的,当然,只能说大多数情况下是如此,并不绝对。

以下是redis的不同数据结构类型的value在不同的情况下会用到的存储结构,一般是面试的时候会问,日常开发不必太深究。第一层是数据结构(数据对象类型),第二层是数据结构可能会调用的存储结构(底层存储类型)。

Redis各种数据的特点:

string 是一个安全的二进制字符串;

双端队列 (链表)list:有序(插入有序);

散列表 hash:对顺序不关注,field 是唯一的;

无序集合 set:对顺序不关注,里面的值都是唯一的;

有序集合 zset:对顺序是关注的,里面的值是唯一的;根据

member 来确定唯一;根据 score 来确定有序。

redis常用的数据类型

redis常用命令一般在官方文档里查询。

string

string存储结构介绍

当value为string类型的时候,字符串长度小于等于 20 且能转成整数,则使用 int 存储;

字符串长度小于等于 44,则使用 embstr 存储;

字符串长度大于 44,则使用 raw 存储。

为什么会有embstr和raw存储的区别?主要是为了字节对齐。

redis的string数据类型小于44字节的时候在底层的存储结构如下:

在没有存储string之前,这个结构体实例包括了前三个属性的大小(16字节),头部信息(3个字节),buf数组\0结尾(1个字节),总共20个字节。

cache line缓存存储的最小单位,用户数据部分大小为64个字节,减去20个字节后还剩44个字节给可以用于string存储。当string小于44个字节,会连同整个结构体一同存储在cache line中,也就是embstr存储。当string大于44个字节,redis会申请一块内存给string,也就是raw存储。

string 与key

redis的key一般也是string类型的。但是key的取名有个点需要注意,比如:如果有多个teacher,可能取名就是就是,不同的teacher对应的key可能就是teacher:10001,teacher:10002。为什么要用冒号分隔,一般是因为redis-cli的可视化工具可以根据冒号更好地进行可视化展开。

string的应用举例

#累加器
# 统计阅读数 累计加1
incr reads
# 累计加100
incrby reads 100
#分布式锁
# 加锁   加锁 和 解析 redis 实现是 非公平锁     ectd
zk 用来实现公平锁
# 阻塞等待   阻塞连接的方式
# 介绍简单的原理: 事务
setnx lock 1   # 不存在才能设置 定义加锁行为 占用锁  
setnx lock uuid  # expire 30 过期
set lock uuid nx ex 30
# 释放锁
del lock
if (get(lock) == uuid)del(lock);
#位运算
# 猜测一下 string 是用的 int 类型 还是 string 类型
# 月签到功能 10001 用户id 202106 2021年6月份的签到 6月
份的第1天
setbit sign:10001:202106 1 1
# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106
# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2

list

list存储结构介绍

双向链表实现,列表首尾操作(删除和增加)时间复杂度O(1);查找中间元素时间复杂度为O(n);
列表中数据是否压缩的依据:1. 元素长度小于 48,不压缩;2. 元素压缩前后长度差不超过 8,不压缩。

list的应用举例

注意,如果要实现阻塞队列,需要至少需要两个进程起redis-cli,一个负责取数据阻塞,一个负责push数据。

#栈
LPUSH + LPOP
# 或者
RPUSH + RPOP
#队列
LPUSH + RPOP
# 或者
RPUSH + LPOP
#阻塞队列
LPUSH + BRPOP
# 或者
RPUSH + BLPOP
#操作与队列一样,但是在不同系统间;生成者和消费者;

hash


hash存储结构介绍

散列表,在很多高级语言当中包含这种数据结构;

c++unordered_map 通过 key 快速索引 value;

hash常用命令

# 获取 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

set

set存储结构介绍

集合;用来存储唯一性字段,不要求有序;存储不需要有序,操作(交并差集的时候排序)

set常用命令

# 添加一个或多个指定的member元素到集合的 key中
SADD key member [member ...]# 计算集合元素个数
SCARD key# SMEMBERS key
SMEMBERS key# 返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member# 随机返回key集合中的一个或者多个元素,不删除这些元素
SRANDMEMBER key [count]# 从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]# 返回一个集合与给定集合的差集的元素
SDIFF key [key ...]# 返回指定所有的集合的成员的交集
SINTER key [key ...]# 返回给定的多个集合的并集中的所有成员
SUNION key [key ...]
#并集
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
# C可能认识的人:sdiff follow:A follow:C

#交集
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
sinter follow:A follow:C

zset

hset存储结构介绍

有序集合实现;用来实现排行榜;它是一个有序唯一;

zst常用命令

# 添加到键为key有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score
member ...]
# 从键为key有序集合中删除 member 的键值对
ZREM key member [member ...]
# 返回有序集key中,成员member的score值
ZSCORE key member
# 为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
# 返回key的有序集元素个数
ZCARD key
# 返回有序集key中成员member的排名
ZRANK key member
# 返回存储在有序集合key中的指定范围的元素   order by id
limit 1,100
ZRANGE key start stop [WITHSCORES]
# 返回有序集key中,指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]

zset应用举例

延时队列:将消息序列化成一个字符串作为 zset 的 member;这个消息的到期处理时间作为 score,然后用多个线程轮询 zset 获取到期的任务进行处理。

def delay(msg):msg.id = str(uuid.uuid4()) #保证 member 唯一value = json.dumps(msg)retry_ts = time.time() + 5 # 5s后重试redis.zadd("delay-queue", retry_ts, value)
# 使用连接池
def loop():while True:values = redis.zrangebyscore("delayqueue", 0, time.time(), start=0, num=1)if not values:time.sleep(1)continuevalue = values[0]success = redis.zrem("delay-queue",
value)if success:msg = json.loads(value)handle_msg(msg)

loop 是多线程竞争,两个线程都从zrangebyscore获取到数据,但是zrem一个成功一个失败。

时间窗口限流:系统限定用户的某个行为在指定的时间范围内(动态)只能发
生 N 次;

# 指定用户 user_id 的某个行为 action 在特定时间内
period 只允许发生该行为做大次数 max_count
local function is_action_allowed(red, userid,
action, period, max_count)local key = tab_concat({"hist", userid,
action}, ":")local now = zv.time()red:init_pipeline()-- 记录行为red:zadd(key, now, now)-- 移除时间窗口之前的行为记录,剩下的都是时间窗口内的记录red:zremrangebyscore(key, 0, now - period*100)-- 获取时间窗口内的行为数量red:zcard(key)-- 设置过期时间,避免冷用户持续占用内存 时间窗口的长度+1秒red:expire(key, period + 1)#commit_pipeline用于执行 Redis 流水线中的所有命令。#返回的列表中的每个元素对应一个命令的执行结果local res = red:commit_pipeline()#res[3] 表示时间窗口内的行为数量(即 red:zcard(key) 命令的返回值)return res[3] <= max_count
end


 


 

相关文章:

Redis相关命令详解及其原理

Redis概念 Redis&#xff0c;英文全称是remote dictionary service&#xff0c;也就是远程字典服务。这是kv存储数据库。Redis&#xff0c;包括所有的数据库&#xff0c;都是请求-回应模式&#xff0c;通俗来说就是数据库不会主动地要给前台推送数据&#xff0c;只有前台发送了…...

go语言中的GoMock

GoMock是一个Go框架。它与内置的测试包整合得很好&#xff0c;并在单元测试时提供了灵活性。正如我们所知&#xff0c;对具有外部资源&#xff08;数据库、网络和文件&#xff09;或依赖关系的代码进行单元测试总是很麻烦。 安装 为了使用GoMock&#xff0c;我们需要安装gomo…...

DIFFWAVE: A VERSATILE DIFFUSION MODEL FOR AUDIO SYNTHESIS (Paper reading)

DIFFWAVE: A VERSATILE DIFFUSION MODEL FOR AUDIO SYNTHESIS Zhifeng Kong, Computer Science and Engineering, UCSD, ICLR2021, Code, Paper 1. 前言 在这项工作中&#xff0c;我们提出了DiffWave&#xff0c;这是一种用于条件和无条件波形生成的多功能扩散概率模型。该模…...

排序算法8----归并排序(非递归)(C)

1、介绍 归并排序既可以是内排序&#xff08;在内存上的数据排序&#xff09;&#xff0c;也可以是外排序&#xff08;磁盘上&#xff09;&#xff08;硬盘&#xff09;&#xff08;在文件中的数据排序&#xff09;。 其他排序一般都是内排序。 区别于快速排序的非递归&#xf…...

Golang 里的 context

context 的作用 go 的编程中&#xff0c;常常会在一个 goroutine 中启动多个 goroutine&#xff0c;然后有可能在这些 goroutine 中又启动多个 goroutine。 如上图&#xff0c;在 main 函数中&#xff0c;启动了一个 goroutine A 和 goroutine B&#xff0c;然后 goroutine A …...

PHP短链接url还原成长链接

在开发过程中&#xff0c;碰到了需要校验用户回填的短链接是不是系统所需要的&#xff0c;于是就需要还原找出短链接所对应的长链接。 长链接转短链接 在百度上搜索程序员&#xff0c;跳转页面后的url就是一个长链接。当然你可以从任何地方复制一个长链接过来。 长链接 http…...

redis原理(三)redis命令

一、字符串命令&#xff1a; 1、字符串基本操作&#xff1a; 2、自增自减 &#xff1a;如果一个值可以被解释为十进制整数或者浮点数&#xff0c;redis允许用户对这个字符串进行INCR*、DECR*操作。 &#xff08;1&#xff09;INCR key&#xff1a;将键存储的值的值加1。 &a…...

教程:在Django中实现微信授权登录

教程&#xff1a;在Django中实现微信授权登录 本教程将引导您如何在Django项目中实现微信授权登录。在本教程中&#xff0c;我们将使用自定义的用户模型User&#xff0c;并通过微信提供的API来进行用户认证。 在进行以下教程之前&#xff0c;请确保你已经在微信开放平台添加了…...

YOLOv5改进 | 主干篇 | 12月份最新成果TransNeXt特征提取网络(全网首发)

一、本文介绍 本文给大家带来的改进机制是TransNeXt特征提取网络,其发表于2023年的12月份是一个最新最前沿的网络模型&#xff0c;将其应用在我们的特征提取网络来提取特征&#xff0c;同时本文给大家解决其自带的一个报错&#xff0c;通过结合聚合的像素聚焦注意力和卷积GLU&…...

【java八股文】之计算机网络系列篇

1、TCP/IP和UDP模型 TCP/IP分层&#xff08;4层&#xff09;&#xff1a;应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层 网络的七层架构 &#xff08;7层&#xff09;&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff…...

SpringAMQP的使用

1. 简介&#xff1a; SpringAMQP是基于RabbitMQ封装的一套模板&#xff0c;并且还利用SpringBoot对其实现了自动装配&#xff0c;使用起来非常方便。 SpringAmqp的官方地址&#xff1a;https://spring.io/projects/spring-amqp SpringAMQP提供了三个功能&#xff1a; 自动声…...

MATLAB - 使用运动学 DH 参数构建机械臂

系列文章目录 前言 一、 使用 Puma560 机械手机器人的 Denavit-Hartenberg (DH) 参数&#xff0c;逐步建立刚体树形机器人模型。在连接每个关节时&#xff0c;指定其相对 DH 参数。可视化机器人坐标系&#xff0c;并与最终模型进行交互。 DH 参数定义了每个刚体通过关节与其父…...

2024年腾讯云新用户优惠云服务器价格多少?

腾讯云服务器租用价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月&#xff0c;云服务器CVM S5实例2核2G配置280.8元一年…...

如何在原型中实现继承和多态

在JavaScript中&#xff0c;我们可以通过原型链来实现继承。以下是如何在原型中实现继承的例子&#xff1a; // 定义一个动物原型 var Animal function() {}; Animal.prototype.move function() { console.log(‘This animal can move.’); }; // 定义一个狗的原型&#xf…...

MySQL/Oracle 的 字符串拼接

目录 MySQL、Oracle 的 字符串拼接1、MySQL 的字符串拼接1.1 CONCAT(str1,str2,...) : 可以拼接多个字符串1.2 CONCAT_WS(separator,str1,str2,...) : 指定分隔符拼接多个字符串1.3 GROUP_CONCAT(expr) : 聚合函数&#xff0c;用于将多行的值连接成一个字符串。 2、Oracle 的字…...

【Java SE语法篇】10.String类

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ 文章目录 前言1. String类1.1 字符串的构造1.2 String对象的比…...

【Python】数据可视化--基于TMDB_5000_Movie数据集

一、数据准备 tmdb_5000_movie数据集下载 二、数据预处理 观察数据集合情况 import pandas as pd import ast import warnings warnings.filterwarnings(ignore) # 加载数据集 df pd.read_csv(tmdb_5000_movies.csv) # 查看数据集信息 print(df.info()) 由于原数据集包含的…...

学习Vue的插槽总结

今天学习了Vue的插槽&#xff0c;在这之前学习使用组件的使用还没有试过在父组件中给子组件插入html结构&#xff0c;今天学习的插槽正是拿来实现这一功能的&#xff0c;这也是一种组件中通信的方式&#xff0c;首先插槽分为三类&#xff1a;默认插槽、具名插槽、作用域插槽。接…...

第九篇 API设计原则与最佳实践

深入浅出HTTP请求前后端交互系列专题 第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述 第二章 HTTP请求方法、状态码详解与缓存机制解析 第三章 前端发起HTTP请求 第四章 前后端数据交换格式详解 第五章 跨域资源共享&#xff08;CORS&#xff09;&#xff1a;现代W…...

新版AndroidStudio配置maven阿里云镜像

project下的build.gradle&#xff1a; // Top-level build file where you can add configuration options common to all sub-projects/modules. // 注意jdk版本需要17以上&#xff0c;因为8.1.3的gradle需要jdk17以上 //plugins { // id com.android.application version…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...