Redis基础1

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: Redis基础

一、Redis简介

Redis是基于键值对形式的NoSQL数据库,在Redis数据库中其键的类型必须是String,但是其值可以是string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、 Bitmaps(位图)、HyperLogLog、GEO(地理信息定位)等多种数据结构和算法组成,所以说Redis能满足多种应用场景,Redis会将所有的数据存放在内存中,还可以将内存中的数据利用快照和日志的形式保存到硬盘中,因此读写性能也较好,并且在发生断电或者机器故障时,内存数据不会丢失。除此之外,Redis还提供键过期、发布订阅、事务、流水线、Lua脚本等附加功能。

Redis的特性

  1. 在内存中存储数据:Redis是通过表来组织存储数据的,属于“关系型数据库”,Redis是通过键值对来存储数据的,key必须是String,Value可以是String、List、Set等数据结构,Redis自身的Hash表是通过哈希表来组织的,属于“非关系型数据库”
  2. 可编程性:可以通过简单的交互式命令或者脚本的方式,批量执行一些操作
  3. 可拓展性:可以在Redis原有提供的API的基础上在进行拓展
  4. 持久性:Redis会把数据主要存储在内存上,硬盘作为辅助(内存的数据备份),如果Redis重启了,就会在重启时加载硬盘中的备份数据,使Redis的内存恢复到重启前的状态。
  5. 支持集群:Redis作为分布式系统的中间件,能存储的数据是有限的,支持集群就能引入多个主机,部署多个Redis节点,每个Redis能够存储一部分数据
  6. 高可用性:Redis自身支持“主从”结构的,从节点相当于对主节点的备份。

Redis的应用场景

  1. 当作数据库使用:Redis是存储在内存中的,访问速度较快,性能较好,Redis中存储的是全量数据,数据不会随便丢失,但是需要更多的硬件资源
  2. 作为缓存使用:Mysql存储数据多,但访问速度较慢,热点数据存储在Redis中(二八原则),Redis存储部分数据,全量数据是存储在Mysql中的,Redis中即使数据丢失也能从Mysql中再进行加载恢复出来的
  3. 会话数据存储在Redis中:之前的session存储在应用服务器中的,现在将会话存储在Redis中时,不论负载均衡器将用户请求放到那个应用服务器,都能通过Redis拿到会话信息,并且在应用重启后session信息不会丢失。
  1. 消息队列(服务器):对于分布式系统中服务器之间可以使用生产者-消费者模型(可以解耦合和削峰填谷),Redis也是客户端-服务器程序(Mysql也是)

Redis过期删除策略

Redis的过期删除策略是定期删除和惰性删除相结合

惰性删除:假设key已经到过期时间了,但是暂时还没有删除,如果后面访问到了这个key,redis服务器就会触发删除key的操作,同时再返回一个nil;

定期删除:每次会抽取一部分,进行验证过期时间,保证抽取检查的过程的速度足够快(Redis是单线程的程序,主要的任务是处理每个命令的任务,如果扫描过期key耗用的时间太多了,正式处理的请求命令就有可能阻塞)

Redis并没有采取定时器的方式来实现过期key的删除

Redis的单线程模型

Redis只用一个线程来处理所有的命令请求(避免了线程安全问题),但并不代表一个Redis服务器进程内部只有一个线程,只是多个线程在处理网络IO,Redis的核心业务逻辑都是短平快的,不太消耗CPU资源,故可以使用单线程模型。


单线程模型的弊端:操作命令占用时间长就会阻塞其他命令的执行


Redis虽然是单线程但是效率高的原因(参照物是数据库(mysql、Oracle、sql server等)):

  1. Redis的操作是访问内存,数据库是访问硬盘
  2. Redis的核心业务比数据库的更简单(数据库对数据的增删改查都有复杂的业务支持,这样的功能会耗用更多的额外开销)
  1. Redis的单线程模型避免了一些不必要的线程进程开销,Redis的核心业务逻辑都是短平快的,不太消耗CPU资源,多个线程对于Redis的提升不大

处理网络IO的时候,使用了epoll这样的IO多路复用机制

二、Redis的全局命令

  • 必须要先进入redis客户端才能操作Redis命令
  • Redis命令不区分大小写
  • Redis内部是按照二进制来存储数据的,要想把二进制字节换回汉字,就需要客户端来支持 redis-cli --raw

keys pattern:查询当前服务器上匹配的key,通过一些特殊符号(通配符)来匹配key,时间复杂度是O(n),执行keys *的时间会非常长,不建议使用


Pattern:包含特殊符号的字符串,为了描述符合要求的字符串


?匹配任意一个字符


* 匹配0个或任意字符


[] 匹配[]其中的任意一个


[^] 排除其中的字符,其余都能匹配


[a-b] 匹配从a到b范围内的字符,包含边界字符


exists key [key...]:判断key是否存在,返回key存在的个数(针对多个key),时间复杂度为O(1),Redis是按照哈希表的方式来存储的


del key [key...]: 删除key,返回删除key的个数,若不存在返回0,时间复杂度为O(1)


expire key seconds:给指定的key设置过期时间,超出指定值就会被自动删除,该命令适用于存在的key,设置成功返回1,失败返回0,时间复杂度为O(1),时间单位是秒(例如短信验证码、优惠券的有效期)


ttl key:查询key的过期时间,key没有设置过期时间返回-1,key不存在返回-2,时间复杂度为O(1)


Flushall:清空redis上的所有数据,相当于清库

三、Redis常见数据类型

String数据类型

常见命令:

SET:将string 类型的value设置到key中。如果key之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此key的TTL也全部失效。


语法格式: SET key value [expiration EX seconds|PX milliseconds] [NX|XX]


时间复杂度:O(1)


选项:


SET命令⽀持多种选项来影响它的⾏为:


• EX seconds⸺使⽤秒作为单位设置key的过期时间。


• PX milliseconds⸺使⽤毫秒作为单位设置key的过期时间。


• NX⸺只在key不存在时才进⾏设置,即如果key之前已经存在,设置不执⾏(不存在才执行)。


• XX⸺只在key存在时才进⾏设置,即如果key之前不存在,设置不执⾏(存在才执行)。


GET:获取key对应的value。如果key不存在,返回nil。如果value的数据类型不是string,会报错。


语法格式: GET key


时间复杂度:O(1)


返回值:key对应的value,或者nil当key不存在。


MSET:⼀次性设置多个key的值。


语法格式: MSET key value [key value ...]


时间复杂度:O(N)N是key数量


返回值:永远是OK


MGET:⼀次性获取多个key的值。如果对应的key不存在或者对应的数据类型不是string,返回nil。


语法格式:MGET key [key ...]


时间复杂度:O(N)N是key数量,命令中key的数量,可以近似认为是O(1)


返回值:对应value的列表


SETNX:设置key-value但只允许在key之前不存在的情况下。


SETXX:设置key-value但只允许在key之前存在的情况下。


SETEX:设置过期时间


PSETEX:设置过期时间,单位是毫秒


语法格式:SETNX key value


时间复杂度:O(1)


返回值:1表⽰设置成功。0表⽰没有设置。


APPEND:如果key已经存在并且是⼀个string,命令会将value追加到原有string的后边。如果key不存在,则效果等同于SET命令


语法格式:APPEND KEY value


时间复杂度:O(1)


返回值:追加完成后string的长度(字节)(utf8编码中一个汉字是3个字节)


GETRANGE:返回key对应的string的⼦串,由start和end确定(左闭右闭)。可以使⽤负数表⽰倒数。-1代表倒数第⼀个字符,-2代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据string的⻓度调整成正确的值。


语法格式:GETRANGE key start end


时间复杂度:O(n)


返回值:string的指定范围的子串


SETRANGE:覆盖字符串的⼀部分,从指定的偏移开始,如果key不存在,会将offset之前的内容填充为0X00


语法格式:SETRANGE key offset value


时间复杂度:O(n)


返回值:替换后string的长度


STRLEN:获取key对应的string的⻓度(单位是字节)。当key存放的类似不是string时,报错。


语法格式:STRLEN key


时间复杂度:O(1)


返回值:string的长度


字符串类型的编码方式:


Int:8个字节类型的长整型


Embstr:小于等于39个字节的字符串,存储小数也是按照压缩字符串类型


Raw:大于39个字节的字符串


String类型的应用场景:

  1. 缓存
  2. 计数
  3. 共享会话
  4. 手机验证码(过期删除)

计数命令:


时间复杂度均是O(1)


INCR:将key对应的string表⽰的数字加⼀。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。


语法格式:INCR key


INCRBY:将key对应的string表⽰的数字加上对应的值。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。


语法格式: INCRBY key decrement


DECR:将key对应的string表⽰的数字减⼀。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。


语法格式:DECR key


DECRBY:将key对应的string表⽰的数字减去对应的值。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。


语法格式:DECRBY key decrement


INCRBYFLOAT:将key对应的string表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果key 不存在,则视为key对应的value是0。如果key对应的不是string,或者不是⼀个浮点数,则报错。允许采⽤科学计数法表示浮点数


语法格式:INCRVYFLAOT key increment

List数据类型

List列表类型:用于存储多个有序的字符串,约定起始下标从左侧0开始,两侧都可以进行插入和删除(可以当作栈和队列来使用)

List列表类型的特点:

列表中的元素是有序的(元素顺序调换和之前的List是不等价的)

区分获取和删除的区别(获取并不会修改列表,但是删除会修改列表)

允许元素重复

常见命令(使用如下命令时要求key对应的value是list,否则就会报错):


LPUSH:将一个或多个元素从左侧(头插)到list中


语法格式:LPUSH key element [element...]


时间复杂度:O(1)


返回值:插入后List的长度


RPUSH:将一个或多个元素从右侧(尾插)到list中


语法格式:RPUSH key element [element...]


时间复杂度:O(1)


返回值:插入后List的长度


LRANGE:获取从start到stop的所有元素,左闭右闭


语法格式:LRANGE key start stop


时间复杂度:O(1)


返回值:指定区间的元素


当区间下标非法时,Redis会尽可能取到给定区间的元素


LPOP:从List左侧取出元素(头删)


语法格式:LPOP key


时间复杂度:O(1)


返回值:取出的元素或者nil


RPOP:从List右侧取出元素(尾删)


语法格式:RPOP key count count参数的使用在redis 6.2以及之后的版本


时间复杂度:O(1)


返回值:取出的元素或者nil


LINDEX:获取从左数第index位置的元素


语法格式:LINDEX key index


时间复杂度:O(N) N指列表的长度 该命令需要遍历链表


返回值:取出的元素或者nil


LINSERT:在特定位置插入元素


语法格式:LINSERT key  pivot element 是在基准元素第一次出现的位置进行插入


时间复杂度:O(N)


返回值:插入成功后List的长度


LLEN:获取List的长度


语法格式:LLEN key


时间复杂度:O(1)


返回值:List的长度


LREM:删除指定的元素


语法格式:LREM key count element    


count是要删除的个数 count>0 从左向右删除, count<0 从右往左删除, count=0删除所有的元素


element是指要删除的值


时间复杂度:O(N)


返回值:成功删除的元素的个数


LTRIM:删除指定范围的元素


语法格式:LRIM key start stop 保留start和stop区间内的元素,将两边的元素进行删除


时间复杂度:O(N)


返回值:是否删除成功


LSET:根据下标修改元素


语法格式:LSET key index element


时间复杂度:O(N)


返回值:下标不合法时会报错,否则返回ok


阻塞版本的命令:


blpop和brpop是lpop和rpop的阻塞版本(阻塞队列,支持“队列为空”的情况,不考虑“队列为满”的情况)和对应的非阻塞版本的作用一致(当list中存在元素时),但仍存在如下区别:


如果list为空,blpop和brpop就会一直阻塞到队列不空为止,阻塞期间Redis依然可以执行别的命令,并且可以显示设置阻塞时间


blpop和brpop可以同时指定多个key,命令中如果设置了多个键,那么就会从左到右来进行遍历,一旦有键对应的链表可以弹出元素,命令就会立即返回


如果多个客户端同时执行一个键pop,则最先执行命令的客户端会得到弹出的元素


BLPOP:从List左侧取出元素(头删)


语法格式:BLPOP key [key …] timeout(单位是s)Redis6允许设置超时时间为小数形式


这些List中右任意一个非空,blpop就都能把这些元素获取到并立即返回


如果这些List都为空,此时就需要进行阻塞等待,等待其他客户端往这些list中插入元素


时间复杂度:O(1)


返回值:


列表非空情况:二元组形式,可以说明数据来源与那个key,以及取到的数据


空列


表情况:进行阻塞等待,得到数据后进行返回,并返回等待时间


list的内部编码:通过quickList进行内部实现,quick List是链表和压缩链表的结合,整体是通过链表实现,链表的每个节点是一个压缩链表,每个压缩列表都不会太大然后用压缩链表进行相连,整体的操作效率高,并且能够节省空间


list类型的应用场景:

  1. 作为类似数组的结构来存储数据(班级中存储学生列表)
  2. 作为消息队列使用(生产者-消费者模型)
  3. 对于一对多场景中进行列表分页
  4. Pipline(流水线)机制,减少网络交互的次数
  5. 选择列表类型时:同侧存取(lpush和lpop或者rpush和rpop)为栈,异侧存取(lpush和rpop或者rpush和lpop)为队列

Hash数据类型

Hash哈希类型:Redis自身属于hash键值对建构,value的类型也可以是Hash表类型(“fileld -> value”),此处的value也可以当作数字进行处理

常见命令:


HSET:设置Hash中指定的字段(field)的值(value),此处的value只能是字符串类型


语法格式:HSET key field value [ field value ...]


时间复杂度:O(1)


返回值:设置成功的键值对的个数


HGET:获取hash中指定字段的值。


语法格式:HGET key field


时间复杂度:O(1)


返回值:字段对应的值或者nil


HEXISTS:判定hash中是否有指定的字段


语法格式: HEXISTS key field


时间复杂度:O(1)


返回值:1表示存在,0表示不存在


HDEL:删除hash中的指定字段


语法格式:HDEL key field


时间复杂度:O(1)


返回值:本次操作成功删除的字段个数


HKEYS:获取hash中的所有字段


语法格式:HKEYS key


时间复杂度:O(N)(N指的是hash表的长度),该操作会根据key找到hash,然后会进行遍历


返回值:字段列表


HVALS:获取hash中所有的值


语法格式:HVALS key


时间复杂度:O(N)


返回值:值列表


HGETALL:获取hash中所有的字段以及对应的值


语法格式:HGETALL key


时间复杂度:O(N)


返回值:所有的字段以及对应的值


HMGET:获取hash中多个field


语法格式:HMGET key field [field...]


时间复杂度:O(N)


返回值: 指定多个字段对应的值(field和value的顺序匹配)


HLEN:获取hash中所有字段的个数


语法格式:HLEN key


时间复杂度:O(1)


返回值:字段个数


HSETNX:在字段不存在的情况下,设置hash中的字段和值


语法格式:HSETNX key field value


时间复杂度:O(1)


返回值:1表示设置成功,2表示设置失败


HINCRBY:将hash字段对应的值添加指定的值


语法格式:HINCRBY key field increment


时间复杂度:O(1)


返回值:该字段变化后的值


HINCRBYFLOAT:将hash字段对应的值添加指定的值(浮点数)


语法格式:HINCRBYFLOAT key field increment


时间复杂度:O(1)


返回值:该字段变化后的值


HASH类型的应用场景:


缓存

作为关系型数据库使用

Redis基础2:https://developer.aliyun.com/article/1521822


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
目录
相关文章
|
算法 安全 数据安全/隐私保护
介绍一下移动应用中的数据加密技术。
移动应用数据加密保护隐私,包括对称加密(速度快但密钥管理难)、非对称加密(公钥私钥确保安全如RSA、ECC)、哈希函数(固定长度输出验证信息)和数字签名(公钥验证来源与完整性)。选择合适的加密算法对安全性至关重要,兼顾性能以不影响用户体验。加密技术确保信息的机密性、真实性和完整性,增强用户信任。开发者应熟练掌握这些工具。
389 0
|
SQL 消息中间件 关系型数据库
实时计算 Flink版产品使用问题之元数据血缘可以通过什么来获取
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
定位技术
高德地图之获取经纬度并且根据获取经纬度渲染到路线规划
高德地图之获取经纬度并且根据获取经纬度渲染到路线规划
302 0
【洛谷 P2669】[NOIP2015 普及组] 金币 题解(循环)
`NOIP2015`普及组题目,骑士按周期领金币:第一天1枚,随后$n$天每天$n$枚,然后$n+1$天每天$n+1$枚。给定天数$k$,求总金币数。输入$k$,输出金币总数。样例输入6,输出14;输入1000,输出29820。代码使用循环和变量控制周期,累计金币数。
334 0
|
存储 分布式计算 Apache
✨[hadoop3.x]新一代的存储格式Apache Arrow(四)
✨[hadoop3.x]新一代的存储格式Apache Arrow(四)
165 1
|
算法
svn导出文件进行比较
之前有介绍svn log 的命令,即可导出版本A~B之间所有的修改动作,然后复制出相应的文件(中间有一个算法去处理每一个动作,然后得到最终需要导出的文件列表,svn常用动作有:Modified、Added、Deleted、Replacing、Conflicted、Merged、Existed等)。
722 0
|
JavaScript 前端开发
JavaScript 中带参数的回调函数
JavaScript 中带参数的回调函数
179 0
|
XML 存储 人工智能
分享:包括 AI 绘画在内的超齐全免费可用的API 大全
我给大家整理了超级齐全的免费可用 API,包括 AI 绘画在内,有需要的小伙伴赶紧收藏了。
1538 0
分享:包括 AI 绘画在内的超齐全免费可用的API 大全
|
存储 缓存 算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
229 0
|
JavaScript 前端开发 容器
vue基础知识和原理(一)
让Vue工作,就须创建一个Vue实例,且要传入一个配置对象 demo容器里的代码符合html规范,只不过混入了一些特殊的Vue语法 demo容器里的代码被称为【Vue模板】 Vue实例和容器是一一对应的 真实开发中只有一个Vue实例,并且会配合着组件一起使用 {{xxx}}是Vue的语法:插值表达式,{{xxx}}可以读取到data中的所有属性 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新(Vue实现的响应式)
315 0
vue基础知识和原理(一)