Redis基础1

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 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数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
机器学习/深度学习 NoSQL Redis
Redis基础
Redis基础
29 0
|
20天前
|
JSON NoSQL Java
|
20天前
|
存储 NoSQL 关系型数据库
|
28天前
|
存储 NoSQL Java
Redis基础2
Redis基础
19 0
|
9月前
|
NoSQL Redis
|
1月前
|
自然语言处理 NoSQL 安全
Redis基础篇:Redis简介和安装
Redis基础篇:Redis简介和安装
|
8月前
|
存储 缓存 NoSQL
04Redis - Redis概述
04Redis - Redis概述
23 0
|
8月前
|
存储 JSON NoSQL
Redis-基础篇
Redis-基础篇
56 0
|
11月前
|
存储 NoSQL Java
深入了解Redis-基础篇
深入了解Redis-基础篇
104 1
|
11月前
|
存储 NoSQL Linux
【Redis 系列】redis 学习二,redis 的特性,安装方式,及为什么 redis 会这么快
【Redis 系列】redis 学习二,redis 的特性,安装方式,及为什么 redis 会这么快