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)
            continue
        value = 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


 


 

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

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

相关文章

【HarmonyOS4.0】第十篇-ArkUI布局容器组件(二)

三、层叠布局容器&#xff08;Stack&#xff09; 堆叠容器组件 Stack的布局方式是把子组件按照设置的对齐方式顺序依次堆叠&#xff0c;后一个子组件覆盖在前一个子组件上边。 注意&#xff1a;Stack 组件层叠式布局&#xff0c;尺寸较小的布局会有被遮挡的风险&#xff0c; …

JS常用插件 Swiper插件 实现轮播图

Swiper介绍 Swiper 是一款免费以及轻量级的移动设备触控滑块的js框架 中文官网地址: https://www.swiper.com.cn/ 点击查看Swiper演示&#xff0c;里面的功能和样式十分丰富&#xff0c;根据自己的需求选择 中文教程中详细介绍了如何使用Swiper API文档中介绍了各个模块以及参…

计算机导论05-计算机网络

文章目录 计算机网络基础计算机网络概述计算机网络的概念计算机网络的功能计算机网络的组成 计算机网络的发展计算机网络的类型 网络体系结构网络互联模型OSI/RM结构与功能TCP/IP结构模型TCP/IP与OSI/RM的比较 网络地址与分配IP地址构成子网的划分IPv6 传输介质与网络设备网络传…

电脑桌面便签在哪设置?备忘录软件哪个好?

好记性不如烂笔头&#xff01;相信很多打工族在电脑面前办公的时候&#xff0c;都需要随时记录工作中的事项&#xff0c;有的用TXT记录&#xff0c;有的手写笔记&#xff0c;还有一些用电脑桌面便签类软件。而当我们待办事项繁多的时候&#xff0c;手写或文本记录并不能有效帮我…

图解python | 字符串及操作

1.Python元组 Python的元组与列表类似&#xff0c;不同之处在于元组的元素不能修改。 元组使用小括号&#xff0c;列表使用方括号。 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可。 tup1 (ByteDance, ShowMeAI, 1997, 2022) tup2 (1…

老师假期有工资么

老师在享受假期的时候&#xff0c;很多人都会好奇&#xff1a;教师寒暑假会有工资吗&#xff1f; 老师也是劳动者&#xff0c;享有法律规定的各种权益。其中之一就是在规定的工作时间内获得报酬。既然老师在正常工作日上班有工资&#xff0c;那么在假期呢&#xff1f; 实际上…

数字化时代,VR全景展示如何让用户一窥全貌?

数字化时代&#xff0c;VR全景展示为各行各业提供了无限的可能性。随着VR全景技术的逐步普及&#xff0c;VR全景展示以其独特的呈现方式和新颖十足的交互体验&#xff0c;正在不断改变着人们对于展示宣传的理解。 传统的展示方式&#xff0c;通常需要将产品、图文、品牌等元素集…

【计算机组成与体系结构Ⅱ】指令调度与分支延迟(实验)

实验4&#xff1a;指令调度与分支延迟 一、实验目的 1. 加深对指令调度技术的理解。 2. 加深对分支延迟技术的理解。 3. 熟练采用指令调度技术解决流水线中的数据冲突的方法。 4. 进一步理解指令调度技术对CPU性能的改进。 5. 进一步理解延迟分支技术对CPU性能的改进。 二…

企业组网搭建有哪些?

在当今全球化的商业环境中&#xff0c;集团公司必须建立起一个无缝连接的网络&#xff0c;以确保高效的信息传输和资源共享。为实现这一目标&#xff0c;选择可靠而安全的网络组网方案至关重要。本文将介绍几种主要的集团公司网络组网方案&#xff0c;以帮助企业根据其具体需求…

人人都在用的PDF软件,也要接入ChatGPT了

随着人工智能技术的不断进步和发展&#xff0c;Chatbot技术的应用已经逐渐从娱乐和社交领域扩展到了更多的实际场景中。在办公软件领域&#xff0c;聊天机器人已经成为了提升工作效率、减少人力投入的重要工具&#xff0c;多家头部企业都在探讨将AI接入到软件及应用中的使用方案…

深入解析阻塞队列BlockingQueue及源码(超详细)

一、基础概念 1.1 BlockingQueue BlockingQueue 是 java.util.concurrent 包提供的用于解决并发生产者 - 消费者问题的最有用的类。 1.1.1 队列类型&#xff1a; 无限队列 &#xff08;unbounded queue &#xff09; - 几乎可以无限增长 有限队列 &#xff08; bounded qu…

python基础语法看一篇就够了,全网最全python语法笔记汇总

前言 Python 是一种代表简单思想的语言&#xff0c;其语法相对简单&#xff0c;很容易上手。不过&#xff0c;如果就此小视 Python 语法的精妙和深邃&#xff0c;那就大错特错了。 如能在实战中融会贯通、灵活使用&#xff0c;必将使代码更为精炼、高效&#xff0c;同时也会极…

Plane Geometry (Junior High School)

初中平面几何&#xff0c; ACBD, ∠CAD60&#xff0c;∠C40&#xff0c;求∠B Vertical Calculation-CSDN博客 Rectangular Area-CSDN博客

Rectangular Area

长方形ABCD&#xff0c; 点E 点F 在边AB上&#xff0c;点A&#xff0c; 点B&#xff0c; 点E&#xff0c; 点F不重合&#xff0c;连接DE&#xff0c;连接CF&#xff0c;相较于点O&#xff0c;已知S△EOF 4&#xff0c; S△COB 16&#xff0c;求S □ABCD &#xff1f; Plane …

YOLO (1) abaconda 安装 cuda、版本确定、pytorch 安装

一、简述 年底了&#xff0c;身上也没有其他项目&#xff0c;恰好乘着这个机会学一下pytorch 和YOLOv8. 1、下载abaconda https://repo.anaconda.com/archive/ 2、安装 环境变量要✔ 其他一直下一步 3、测试 (base) C:\Users\alber>conda -V conda 23.1.0(base) C…

算法通关村第十四关—数据流的中位数(黄金)

数据流中中位数的问题 LeetCode295,中位数是有序列表中间的数。如果列表长度是偶数&#xff0c;中位数则是中间两个数的平均值。 例如&#xff1a;[2,3,4]的中位数是3 [2,3]的中位数是(23)/22.5 实现 MedianFinder 类: MedianFinder() 初始化 MedianFinder 对象。void addNum(…

漏洞修复整理

一、Geoserver Apache HTTP/2拒绝服务漏洞&#xff08;CVE-2023-44487&#xff09;、Eclipse Jetty 资源管理错误漏洞(CVE-2023-26048)、Eclipse Jetty 信息泄露漏洞(CVE-2023-26049) 受影响版本&#xff1a;9.4.53以下版本 处理方式&#xff1a;原地升级 &#xff08; jdk版本…

开源ERP系统Odoo安装部署并结合内网穿透实现公网访问本地系统

文章目录 前言1. 下载安装Odoo&#xff1a;2. 实现公网访问Odoo本地系统&#xff1a;3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件&#xff0c;是一个一站式全功能ERP及电商平台。 开源性质&#xff1a;Odoo是一个开源的ERP软件&#xff0c;这意味着企…

ESP系列入门教程(二)——之简单驱动温湿度传感器DHT11【附 ESP32 / ESP8266 通用代码】

ESP系列入门教程<二> 概要技术名词简介● ESP系列简介 硬件连接实现代码实现●Demo&#xff1a;驱动DHT11温湿度传感器●编译注意事项&#xff1a;添加DHT库 概要 最近在跟着几个大佬的教学视频做项目。陆续会更新记录一些要点&#xff0c;便于后期总结笔记的时候进行引…

鸿蒙开发OpenHarmony组件复用案例

概述 在开发应用时&#xff0c;有些场景下的自定义组件具有相同的组件布局结构&#xff0c;仅有状态变量等承载数据的差异。这样的组件缓存起来&#xff0c;需要使用到该组件时直接复用&#xff0c; 减少重复创建和渲染的时间&#xff0c;从而提高应用页面的加载速度和响应速度…