Redis的应用详解

Posted 耳冉鹅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis的应用详解相关的知识,希望对你有一定的参考价值。

一、NoSQL

1、概述

为了解决高并发、高可扩展、高可用、大数据存储问题而产生的数据库解决方案,就是NoSql数据库。

NoSQL,泛指非关系型的数据库,NoSQL即Not-Only SQL,它可以作为关系型数据库的良好补充

2、为什么使用NoSQL

1 mysql时代

在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。

在那个时候,更多的都是静态网页,动态交互类型的网站不多。

服务器根本没有太大的压力!

在这里插入图片描述

思考:随着时代的发展,网站的瓶颈是什么?

1.数据量的总大小 一个机器放不下时

2.数据的索引(B+ Tree)一个机器的内存放不下时(数据量大)

3.访问量(读写混合)一个实例不能承受

如果满足了上述1 or 3个,需要升级

2 Memcached+MySQL+垂直拆分

后来,随着访问量的上升,几乎大部分使用MySQL架构的网站在数据库上都开始出现了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。程序员们开始大量的使用缓存技术来缓解数据库的压力,优化数据库的结构和索引。

  • 开始比较流行的是通过文件缓存来缓解数据库压力
    • 是当访问量继续增大的时候,多台web机器通过文件缓存不能共享,大量的小文件缓存也带了了比较高的IO压力。在这个时候,Memcached就自然的成为一个非常时尚的技术产品。
  • Memcached作为一个独立的分布式的缓存服务器,为多个web服务器提供了一个共享的高性能缓存服务
  • 由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。由此引出数据库的从复制技术来达到读写分离,以提高读写性能和读库的可扩展
    • Mysql的master-slave模式成为这个时候的网站标配了

在这里插入图片描述

3 分库分表+水平拆分+MySQL集群

在Memcached的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁(锁定某张表),在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM,InnoDB是行锁(锁定指定行记录)。

同时,开始流行使用分表分库来缓解写压力和数据增长的扩展问题。这个时候,分表分库成了一个热门技术,是面试的热门问题也是业界讨论的热门技术问题。也就在这个时候,MySQL推出了还不太稳定的表分区,这也给技术实力一般的公司带来了希望。虽然MySQL推出了MySQL Cluster集群,但性能也不能很好满足互联网的要求,只是在高可靠性上提供了非常大的保证。

在这里插入图片描述

出现发展瓶颈

​ MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。

4 解决方案

MySQL 等关系型数据库就不够用了!数据量很多,变化很快~!

MySQL 有的使用它来存储一些比较大的文件,博客,图片!数据库表很大,效率就低了!如果有一种数 据库来专门处理这种数据

在这里插入图片描述

用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长! 这时候我们就需要使用NoSQL数据库的,Nosql可以很好的处理以上的情况

5 NoSQL特点
  • 方便扩展(数据之间没有关系,很好扩展!)

  • 大数据量高性能(Redis 一秒写8万次,读取11万,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)

  • 数据类型是多样型的!(不需要事先设计数据库!随取随用!)

  • 传统 RDBMS 和 NoSQL对比

    • RDBMS

      - 高度组织化结构化数据

      - 结构化查询语言(SQL)

      - 数据和关系都存储在单独的表中。

      - 数据操纵语言,数据定义语言

      - 严格的一致性

      - 基础事务

    • NoSQL

      - 代表着不仅仅是SQL

      - 没有声明性查询语言

      - 没有预定义的模式

      - 键 - 值对存储,列存储,文档存储,图形数据库

      - 最终一致性,而非ACID属性

      - 非结构化和不可预知的数据

      - CAP定理

      - 高性能,高可用性和可伸缩性

  • 一般来说现在公司更多的情况是Mysql+NoSQL共同使用

3、新时代的 3V、3高

3V

  • 海量Velume

  • 多样Variety

  • 实时Velocity

3高

  • 高并发

  • 高可扩

  • 高性能

4、使用场景

缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用

分布式集群架构中的session分离。

聊天室的在线好友列表。

任务队列。(秒杀、抢购、12306等等)

应用排行榜。

网站访问统计。

数据过期处理(可以精确到毫秒)

二、NoSQL四大分类

1、分类

KV键值对

  • 新浪:BerkeleyDB+redis
  • 美团:redis+tair
  • 阿里、百度:memcache+redis

文档型数据库

  • CouchDB
  • MongoDB
    • 这个数据库目前市面上使用较多, 前端也常使用
    • MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
    • MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

列存数据库

  • Cassandra, HBase
  • 分布式文件系统

图关系数据库

  • 它不是放图形的,放的是关系比如:朋友圈社交网络、广告推荐系统,社交网络,推荐系统等。专注于构建关系图谱

  • Neo4J, InfoGrid

2、对比图

在这里插入图片描述

三、分布式相关理念

1、ACID

  • A (Atomicity) 原子性

原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚

  • C (Consistency) 一致性

一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

  • I (Isolation) 独立性

所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的

  • D (Durability) 持久性

持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

2、CAP理论

  1. C:Consistency(强一致性)
  2. A:Availability(可用性)
  3. P:Partition tolerance(分区容错性)

CAP理论在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。(异地多活)

所以我们只能在一致性和可用性之间进行权衡,没有NoSQL系统能同时保证这三点。

1 如何选择

CA 传统Oracle数据库

AP 大多数网站架构的选择

CP Redis、Mongodb

一致性和可用性之间取一个平衡。多余大多数web应用,其实并不需要强一致性。
因此牺牲C换取P,这是目前分布式数据库产品的方向

2 原因

​ 对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比方说发一条消息之 后,过几秒乃至十几秒之后,我的订阅者才看到这条动态是完全可以接受的。

​ 对复杂的SQL查询,特别是多表关联查询的需求

​ 任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的报表查询,特别是SNS类型的网站,从需求以及产品设计角 度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能被极大的弱化了

3 图解

在这里插入图片描述

3、解决关系数据库弱势(BASE)

BASE其实是下面三个术语的缩写:

基本可用(Basically Available):当分布式系统出现不可预见的故障时,允许损失部分可用性,保障系统的基本可用

如:部分用户双十一高峰期淘宝页面卡顿或降级处理

软状态(Soft state):允许系统中的数据存在中间状态,既系统的不同节点的数据副本之间的数据同步过程存在延时,并认为这种延时不会影响系统可用性

如:12306网站卖火车票,请求会进入排队队列

最终一致(Eventually consistent):所有的数据在经过一段时间的数据同步后,最终能够达到一个一致的状态

理财产品首页充值总金额短时不一致

它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观。为什么这么说呢,缘由就在于大型系统往往由于地域分布和极高性能的要求,不可能采用分布式事务来完成这些指标,要想获得这些指标,我们必须采用另外一种方式来完成,这里BASE就是解决这个问题的办法

4、分布式与集群

什么是分布式?

分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。

简单来说:

分布式:不同的多台服务器上面部署不同的服务模块(工程),他们之间通过Rpc/Rmi之间通信和调用,对外提供服务和组内协作。

在这里插入图片描述

什么是集群?

通过多台计算机完成同一个工作,达到更高的效率

在这里插入图片描述

四、Redis入门

1、Redis是什么

Redis:REmote DIctionary Server(远程字典服务器)

是完全开源免费的,用C语言编写的,遵守BSD协议,

是一个高性能的(key/value)分布式内存数据库,基于内存运行

并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,

也被人们称为数据结构服务器

2、Redis的特点

  1. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
  3. Redis支持数据的备份,即master-slave模式的数据备份

3、Redis能做什么

  1. 内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
  2. 取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
  3. 模拟类似于HttpSession这种需要设定过期时间的功能
  4. 发布、订阅消息系统
  5. 定时器、计数器

下载地址

http://redis.io/

http://www.redis.cn/

4、Redis安装

提示: redis有window版和Linux版(推荐)

1 Windows版本
  • windows版本下载后解压就行
  • 想要在windows上打开redis, 要先打开服务器端, 再打开客户端

在这里插入图片描述

2 Linux版本
  • 先安装好VM与Linux系统

  • 在Linux下安装gcc环境

    • yum install gcc-c++
      
  • 下载源码包上传到Linux系统的/opt目录下

  • 或者可以进入/opt目录使用以下命令下载

    • wget http://download.redis.io/releases/redis-5.0.5.tar.gz
      
  • 复制压缩文件到/usr/local/目录下,解压

    • [root@admin opt]# cp redis-5.0.5.tar.gz /usr/local/src/
      [root@admin opt]# cd /usr/local/src/
      [root@admin src]# tar -zxvf redis-5.0.5.tar.gz
      
  • 进入解压后的文件目录,编译,安装

    • $ cd redis-5.0.5 
      $ make 
      $ make install PREFIX=/usr/local/redis-5.0.5
      
3 Redis启动

前端启动

有弊端, 页面不能退出, 退出就是服务器停止了

  1. 进入启动目录

    1. cd /usr/local/redis-5.0.5/bin/
  2. 执行启动服务器

    1. ./redis-server

    ctrl+c退出

后台启动

后台启动需要修改redis的配置文件, 可以复制一份配置文件从redis源码种到/usr/local/的redis目录下

之后启动redis的时候用这个文件作为启动项

[root@admin bin]# cd /usr/local/src/redis-5.0.5
[root@admin redis-5.0.5]# cp redis.conf /usr/local/redis-5.0.5/
[root@admin redis-5.0.5]# vim /usr/local/redis-5.0.5/redis.conf

在这里插入图片描述

以修改后的配置文件来启动服务器

[root@admin redis-5.0.5]# cd /usr/local/redis-5.0.5/bin/
[root@admin bin]# ./redis-server /usr/local/redis-5.0.5/redis.conf

启动客户端

#同样在src目录下 
[root@admin bin]# ./redis-cli
127.0.0.1:6379>
# 显示的命令发生改变表示成功
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> get k1
"hello"
127.0.0.1:6379>

5、压力测试

redis-benchmark 是一个压力测试工具

使用参考

https://www.runoob.com/redis/redis-benchmarks.html

指令

redis-benchmark [option] [option value]

在这里插入图片描述

测试1000个实例

[root@admin bin]# ./redis-benchmark -n 1000 -q
PING_INLINE: 166666.67 requests per second
PING_BULK: 124999.99 requests per second
SET: 142857.14 requests per second
GET: 166666.67 requests per second
INCR: 124999.99 requests per second
LPUSH: 166666.67 requests per second
RPUSH: 142857.14 requests per second
LPOP: 200000.00 requests per second
RPOP: 200000.00 requests per second
SADD: 166666.67 requests per second
HSET: 124999.99 requests per second
SPOP: 166666.67 requests per second
LPUSH (needed to benchmark LRANGE): 200000.00 requests per second
LRANGE_100 (first 100 elements): 76923.08 requests per second
LRANGE_300 (first 300 elements): 32258.06 requests per second
LRANGE_500 (first 450 elements): 21276.60 requests per second
LRANGE_600 (first 600 elements): 17543.86 requests per second
MSET (10 keys): 142857.14 requests per second

Redis 为什么单线程还这么快?

​ 误区1:高性能的服务器一定是多线程的?

​ 误区2:多线程(CPU上下文会切换!)一定比单线程效率高! 先去CPU>内存>硬盘的速度要有所了解!

​ 核心:redis 是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是高的,多线程 (CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是高 的!多次读写都是在一个CPU上的,在内存情况下,这个就是佳的方案!

6、Redis库相关指令

  • 默认16个数据库,类似数组下表从零开始,初始默认使用零号库

    • select令切换数据库

    • 127.0.0.1:6379> select 2
      OK
      127.0.0.1:6379[2]> 
      
  • dbsize查看当前数据库的key的数量

    • 127.0.0.1:6379[2]> select 0
      OK
      127.0.0.1:6379> dbsize
      (integer) 5
      127.0.0.1:6379> 
      
  • flflushdb:清空当前库

    • 127.0.0.1:6379> set k1 abc
      OK
      127.0.0.1:6379> set k2 cba
      OK
      127.0.0.1:6379> dbsize
      (integer) 6
      127.0.0.1:6379> flushdb
      OK
      127.0.0.1:6379> dbsize
      (integer) 0
      127.0.0.1:6379> 
      
  • Flushall:通杀全部库

7、关于Keys的相关指令

1 设置key的生存时间

Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁。

基本语法

EXPIRE key seconds #设置key的生存时间(单位:秒)key在多少秒后会自动删除 
TTL key #查看key剩余的生存时间 
PERSIST key #清除生存时间 
PEXPIRE key milliseconds #生存时间设置单位为:毫秒

案例

127.0.0.1:6379> set test 1	#设置test的值为1
OK
127.0.0.1:6379> get test	#获取test的值
"1"
127.0.0.1:6379> expire test 5	#设置test的生存时间为5秒
(integer) 1
127.0.0.1:6379> ttl test	#查看test的生于生成时间还有2秒删除
(integer) 2
127.0.0.1:6379> ttl test
(integer) -2
127.0.0.1:6379> get test	#获取test的值,已经删除
(nil)
2 keys

返回满足给定pattern 的所有key

基本语法

keys * # 可以是*也可以是相关的某字段*

案例

127.0.0.1:6379> set a1 1
OK
127.0.0.1:6379> set a2 2
OK
127.0.0.1:6379> set asd 3
OK
127.0.0.1:6379> set a34 4
OK
127.0.0.1:6379> keys a*
1) "a2"
2) "a1"
3) "a34"
4) "asd"
127.0.0.1:6379> 
3 exists

确认一个key 是否存在

示例:从结果来看,数据库中不存在HongWan 这个key,但是age 这个key 是存在的

基本语法

exists key

案例

127.0.0.1:6379> exists asd
(integer) 1
127.0.0.1:6379> exists a3
(integer) 0
4 del

删除一个key

基本语法

del key

案例

127.0.0.1:6379> del asd
(integer) 1
127.0.0.1:6379> exists asd
(integer) 0
5 rename

重命名key

基本语法

rename oldKey newKey
6 type

返回值的类型

基本语法

type key

案例

127.0.0.1:6379> type addr 
string 
127.0.0.1:6379> type myzset2
zset 
127.0.0.1:6379> type mylist 
list

8、Redis常用数据类型

  • 字符串类型(String)
  • 散列类型(Hash)
  • 列表类型(List)
  • 集合类型(Set)
  • 有序集合类型(SortedSet)
1 String

赋值

语法:SET key value 
127.0.0.1:6379> set test 123 
OK

取值

语法:GET 
key 127.0.0.1:6379> get test 
"123“

设置/获取多个键值

语法:
	MSET key value [key value …] 
	MGET key [key …] 
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 
OK
127.0.0.1:6379> get k1 
"v1" 
127.0.0.1:6379> mget k1 k3 
1) "v1" 
2) "v3"

取值并赋值

语法:GETSET key value 
127.0.0.1:6379> getset s2 222 
"111" 
127.0.0.1:6379> get s2 
"222"

删除

语法:DEL key 
127.0.0.1:6379>del test 
(integer) 1

数值增减

当存储的字符串是整数时,Redis提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递增后的值。

语法:INCR key 
127.0.0.1:6379> incr num 
(integer) 1
127.0.0.1:6379> incr num 
(integer) 2 
127.0.0.1:6379> incr num
(integer) 3
###################################### 
增加指定的整数 
语法:INCRBY key increment 
127.0.0.1:6379> incrby num 2 
(integer) 5 
127.0.0.1:6379> incrby num 2 
(integer) 7 
127.0.0.1:6379> incrby num 2 
(integer) 9 
################################ 
递减数值 
语法:DECR key 
127.0.0.1:6379>decr num
(integer) 9 
127.0.0.1:6379>decr num 
(integer) 8 
#################################### 
减少指定的整数 
语法:DECRBY key decrement 
127.0.0.1:6379> decr num 
(integer) 6 
127.0.0.1:6379> decr num 
(integer) 5 
127.0.0.1:6379> decrby num 3
(integer) 2 
127.0.0.1:6379> decrby num 3
(integer) -1 
#######################################

向尾部追加值

APPEND的作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value,即相当于SET key value。返回值是追加后字符串的总长度

语法:APPEND key value 

127.0.0.1:6379> set str hello 
OK
127.0.0.1:6379> append str " world!" 
(integer) 12 
127.0.0.1:6379> get str 
"hello world!"

获取字符串长度

STRLEN命令返回键值的长度,如果键不存在则返回0。

语法:STRLEN key 
127.0.0.1:6379> strlen str 
(integer) 0 
127.0.0.1:6379> set str hello 
OK
127.0.0.1:6379> strlen 
str (integer) 5
2 Hash

hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。如下:

在这里插入图片描述

赋值

HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。

#一次只能设置一个字段值 
语法:HSET key field value 
127.0.0.1:6379> hset user username zhangsan
(integer) 1 
#一次可以设置多个字段值 
语法:HMSET key field value [field value ...] 
127.0.0.1:6379> hmset user age 20 username lisi 
OK
#当字段不存在时赋值,类似HSET,区别在于如果字段存在,该命令不执行任何操作 
语法:HSETNX key field value 
127.0.0.1:6379> hsetnx user age 30 
#如果user中没有age字段则设置age值为30,否则不做任何操作
(integer) 0

取值

#一次只能获取一个字段值 
语法:HGET key field 
127.0.0.1:6379> hget user username 
"zhangsan“ 
#一次可以获取多个字段值 
语法:HMGET key field [field ...] 
127.0.0.1:6379> hmget user age username 
1) "20" 
2) "lisi" 
#获取所有字段值 
语法:HGETALL key
127.0.0.1:6379> hgetall user 
1) "age" 
2) "20" 
3) "username" 
4) "lisi"

删除字段

可以删除一个或多个字段,返回值是被删除的字段个数

#语法:HDEL key field [field ...] 
127.0.0.1:6379> hdel user age 
(integer) 1 
127.0.0.1:6379> hdel user age name 
(integer) 0 
127.0.0.1:6379> hdel user age username
(integer) 1
3 List

ArrayList与LinkedList的区别

ArrayList使用数组方式存储数据,所以根据索引查询数据速度快,而新增或者删除元素时需要设计到位移操作,所以比较慢

LinkedList使用双向链表方式存储数据,每个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快。然后通过下标查询元素时需要从头开始索引,所以比较慢,但是如果查询前几个元素或后几个元素速度比较快

在这里插入图片描述
在这里插入图片描述

Redis的list

列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段

列表类型内部是使用双向链表(double linked list)实现的,所以获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的

向列表两端增加元素

# 向列表左边增加元素 
语法:LPUSH key value [value ...] 
127.0.0.1:6379> lpush list 1 2 3 
(integer) 3 
# 向列表右边增加元素 
语法:RPUSH key value [value ...] 
127.0.0.1:6379> rpush list a b c 
(integer) 3

查看列表

LRANGE命令是列表类型最常用的命令之一,获取列表中的某一片段,将返回start、stop之间的所有元素(包含两端的元素),索引从0开始。索引可以是负数,如:“-1”代表最后边的一个元素。

#语法:LRANGE key start stop 
127.0.0.1:6379> lrange list 0 5 
1) "3" 
2) "2"
3) "1" 
4) "a"
5) "b"
6) "c"

从列表两端弹出元素

LPOP命令从列表左边弹出一个元素,会分两步完成:

第一步是将列表左边的元素从列表中移除

第二步是返回被移除的元素值。

语法:
	LPOP key 
	RPOP key 
127.0.0.1:6379> lpop list 
"c“ 
127.0.0.1:6379> rpop list 
"3“

获取列表中元素的个数

语法:LLEN key 
127.0.0.1:6379> llen list 
(integer) 4

获得/设置指定索引的元素值

#获得指定索引的元素值 
语法:LINDEX key index 
127.0.0.1:6379> lindex list 2 
"1" 
#设置指定索引的元素值
语法:LSET key index value 
127.0.0.1:6379> lset list 2 2 
OK
127.0.0.1:6379> lrange list 0 -1 ``#//查询所有 
1) "6"
2) "5" 
3) "2" 
4) "2"

向列表中插入元素

该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。

#语法:LINSERT key BEFORE|AFTER pivot value 
127.0.0.1:6379> lrange list 0 -1 
1) "3" 
2) "2"
3) "1" 
127.0.0.1:6379> linsert list after 3 4 
(integer) 4 
127.0.0.1:6379> lrange list 0 -1 
1) "3" 
2) "4" 
3) "2"
4) "1"

将元素从一个列表转移到另一个列表中

语法:RPOPLPUSH source destination 
127.0.0.1:6379> rpoplpush list newlist "
1" 
127.0.0.1:6379> lrange newlist 0 -1 
1) "1" 
127.0.0.1:6379> lrange list 0 -1 
1) "3" 
2) "4" 
3) "2"
4 Set

集合中的数据是不重复且没有顺序。

集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在

Redis还提供了多个集合之间的交集、并集、差集的运算。

在这里插入图片描述

增加/删除元素

#语法:SADD key member [member ...]/增加 
127.0.0.1:6379> sadd key1 a b c 
(integer) 3 
127.0.0.1:6379> sadd key1 a 
(integer) 0 
#语法:SREM key member [member ...]/删除 1
27.0.0.1:6379> srem set c 
d (integer) 1

获得集合中的所有元素

语法:SMEMBERS key 
127.0.0.1:6379> smembers key1 
1) "b" 
2) "a”

判断元素是否在集合中

语法:SISMEMBER key member 
127.0.0.1:6379> sismember set a 
(integer) 1 
127.0.0.1:6379> sismember set h 
(integer) 0

运算命令

集合的差集运算A-B

在这里插入图片描述

属于A并且不属于B的元素构成的集合

语法:SDIFF key [key ...] 
127.0.0.1:6379> sadd setA 1 2 3
(integer) 3 
127.0.0.1:6379> sadd setB 2 3 4 
(integer) 3 
127.0.0.1:6379> sdiff setA setB 
1) "1" 
127.0.0.1:6379> sdiff setB setA 
1) "4"

集合的交集运算A∩B

在这里插入图片描述

属于A且属于B的元素构成的集合。

语法:SINTER key [key ...] 
127.0.0.1:6379> sinter setA setB 
1) "2" 
2) "3"

集合的并集运算A∪B
在这里插入图片描述

属于A或者属于B的元素构成的集合

语法:SUNION key [key ...] 
127.0.0.1:6379> sunion setA setB 
1) "1" 
2) "2" 
3) "3"
4) "4"

获得集合中元素的个数

语法:SCARD key 
127.0.0.1:6379> smembers setA 
1) "1" 
2) "2" 
3) "3" 
127.0.0.1:6379> scard setA 
(integer) 3

从集合中弹出一个元素

注意:由于集合是无序的,所有SPOP命令会从集合中随机选择一个元素弹出

语法:SPOP key 
127.0.0.1:6379> spop setA 
"1“
5 SortedSet :zset

在集合类型的基础上,有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关的操作。

在某些方面有序集合和列表类型有些相似。

1、二者都是有序的。

2、二者都可以获得某一范围的元素。

但是,二者有着很大区别:

1、列表(List)类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度

会变慢。

2、有序集合(SortedSet)类型使用散列表实现,所有即使读取位于中间部分的数据也很快。

3、列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)

4、有序集合要比列表类型更耗内存

增加元素

向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入

到集合中的元素个数,不包含之前已经存在的元素。

语法:ZADD key score member [score member ...] 
127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu 
(integer) 3 
127.0.0.1:6379> zadd scoreboard 97 lisi 
(integer) 0

获取元素的分数

语法:ZSCORE key member 
127.0.0.1:6379> zscore scoreboard lisi 
"97"

删除元素

移除有序集key中的一个或多个成员,不存在的成员将被忽略。

当key存在但不是有序集类型时,返回一个错误。

语法:ZREM key member [member ...] 
127.0.0.1:6379> zrem scoreboard lisi 
(integer) 1

获得排名在某个范围的元素列表

按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

语法:ZRANGE key start stop [WITHSCORES] 
127.0.0.1:6379> zrange scoreboard 0 2 
1) "zhangsan" 
2) "wangwu" 
3) "lisi“

按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

语法:ZREVRANGE key start stop [WITHSCORES] 
127.0.0.1:6379> zrevrange scoreboard 0 2 
1) " lisi " 
2) "wangwu" 
3) “zhangsan”

如果需要获得元素的分数的可以在命令尾部加上***WITHSCORES***参数

127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES 
1) "zhangsan" 
2) "80" 
3) "wangwu" 
4) "94"

获得指定分数范围的元素

语法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES 
1) "wangwu" 
2) "94" 
3) "lisi" 
4) "97" 
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2 
1) "wangwu" 
2) "lisi"

增加某个元素的分数

返回值是更改后的分数

语法:ZINCRBY key increment【要增加的分数】 member 
127.0.0.1:6379> ZINCRBY scoreboard 4 lisi 
"101“

获得集合中元素的数量

语法:ZCARD key 
127.0.0.1:6379> ZCARD scoreboard 
(integer) 3

获得指定分数范围内的元素个数

语法:ZCOUNT key min max 
127.0.0.1:6379> ZCOUNT scoreboard 80 90 
(integer) 1

按照排名范围删除元素

语法:ZREMRANGEBYRANK key start stop 
127.0.0.1:6379> ZREMRANGEBYRANK scoreboard 0 1 
(integer) 2 
127.0.0.1:6379> ZRANGE scoreboard 0 -1 
1) "lisi"

按照分数范围删除元素

语法:ZREMRANGEBYSCORE key min max 
127.0.0.1:6379> zadd scoreboard 84 zhangsan 
(integer) 1 
127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100 
(integer) 1

获取元素的排名

以上是关于Redis的应用详解的主要内容,如果未能解决你的问题,请参考以下文章

Redis实现分布式锁(设计模式应用实战)

Redis实现分布式锁(设计模式应用实战)

Redis五大数据类型详解

如何利用redis来进行分布式集群系统的限流设计

详解 Redis 应用场景及原理

Redis详解包含:B站面试问题及详解