Redis(一):Redis 五大基本数据类型详述

Redis 概述

官方中文网址:http://www.redis.cn/
Redis(Remote Dictionary Server ),译为:远程字典服务

它是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
在这里插入图片描述
Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave (主从) 同步。
免费和开源,使它成为了当下最热门的 NoSQL 技术之一,也被人们称之为结构化数据库。

Redis是单线程的,官方表示,Redis是基于内存操作的,CPU不是Redis的瓶颈,它的瓶颈是机器的内存和带宽。

核心:Redis 是将所有的数据全部存放在内存之中的,所以说使用单线程效率就是最高的,多线程会产生CPU上下文切换,会增加耗时,而我们所有的文件都在内存中,对于内存系统来说,没有上下文切换效率就是最高的,多次读写都在一个CPU上,这就是最佳的方案。

使用 Redis 我们可以做什么:

  • 内存存储、持久化
  • 效率高,可以用于高速缓存
  • 发布订阅系统
  • 地图信息分析
  • 计时器、计数器(浏览量)

补充说明 NoSQL

1、NoSQL 全称为 Not Only SQL,译为:非关系型数据库。

2、为什么要用 NoSQL?
在90年代,一个网站的访问量一般不会太大,使用单个数据库完全足够,那个时候,更多的是使用静态网页 Html, 服务器没有太大的压力。
随着互联网的发展,数据越来越多,越来越复杂,数据库需要来存储一些较大的文件,如:博客,图片,这时关系型数据库的表会很大,效率降低。
2010年 ~ 2020年,这十年间,用户的个人信息,社交网络,地理位置,用户自己产生的数据,用户日志等数据成爆发式增长,一些关系型数据库更不能满足要求,这时 Nosql 出现了,它可以很好的处理以上的情况。

3、NoSQL 的特点

  • 方便扩展(数据之间没有关系,很好扩展)
  • 大数据量,高性能(Redis 一秒写8万次,读取11万,NoSQL的缓存记录级,是一种细粒度的缓存,性能比较高)
  • 数据类型是多样型的(不需要事先设计数据库,随取随用)

Redis 的安装

本篇仅为 Redis 练习所用,所以只准备了 Windows 的 Redis 安装包和可视化管理工具
网盘链接:https://pan.baidu.com/s/1UiAAns788lJe1X8J7dq-zQ
提取码:rzcp
下载完直接解压即可使用,在练习过程中,需要一直开启服务端,才能保证客户端正常使用
在这里插入图片描述
安装完成后,我们来测试使用,打开服务端
在这里插入图片描述
再打开客户端,输入 ping ,回显 pong ,表示 Redis 连接成功
在这里插入图片描述

Redis 的五大基本数据结构

我们先来了解下 Redis 存储数据的结构,基本上 Redis 存储的数据都是键值对(Key - value),下面我们来举例子说明 Redis 的存储结构
Redis-Key

127.0.0.1:6379> ping
PONG
127.0.0.1:6379> keys *         # 获取所有的 key
(empty list or set)
127.0.0.1:6379> set name zhangsan   # 设置key
OK
127.0.0.1:6379> set age 13          
OK 
127.0.0.1:6379> keys *              # 获取所有的 key
1) "name"
2) "age"
127.0.0.1:6379> get name            # 根据 key 获取 value 值
"zhangsan"
127.0.0.1:6379> get age
"13"
127.0.0.1:6379> exists name         # 判断当前的 key 是否存在,存在放回 1,不存在返回 0
(integer) 1
127.0.0.1:6379> exists age
(integer) 1
127.0.0.1:6379> exists id
(integer) 0 
127.0.0.1:6379> move name 1         # 移除当点 key
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> expire name 10       # 设置 key 的过期时间,单位是 秒
(integer) 1
127.0.0.1:6379> ttl name
(integer) 7
127.0.0.1:6379> ttl name             # name 剩 4s 过期
(integer) 4
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> type age              # 查看当前 key 的类型
string

String(字符串)

设置键值,获取键值

127.0.0.1:6379> set key1 v1     # 设置一个键叫 key1,值为 v1
OK
127.0.0.1:6379> get key1        # 获取键对应的值
"v1"

判断某个键是否存在,往某个键中追加字符串,获取字符串的长度

127.0.0.1:6379> exists key1
(integer) 1
127.0.0.1:6379> append key1 ",hello"  # 向某个键中,追加字符串
(integer) 8
127.0.0.1:6379> strlen key1           # 获取字符串的长度
(integer) 8
127.0.0.1:6379> get key1
"v1,hello"
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> append key2 world     # 当追加字符串的键不存在时,会创建这个键
(integer) 5
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
127.0.0.1:6379> get key2
"world"

自增,自减,设置自增步长,自减步长
我们通常使用这些代码做页面浏览量的统计

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views            # 默认步长为 1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> incrby views 10      # 设置自增步长为 10
(integer) 12
127.0.0.1:6379> get views
"12"
127.0.0.1:6379> decr views           # 默认自减步长为 1 
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 15      # 设置自减步长为 15
(integer) -4
127.0.0.1:6379> get views
"-4"

截取字符串,包括截取两端,截取的是一个闭区间内的字符串,但是,当截取的长度为 [0,-1] 时,这时 getrange 会返回整个字符串
setrange 从指定字符的下一个开始,将原字符串中的字符,对应个数替换为我们输入的,不改变其余的字符

127.0.0.1:6379> set key1 "hello,world"
OK
127.0.0.1:6379> get key1
"hello,world"
127.0.0.1:6379> getrange key1 0 4  # 截取字符串
"hello"
127.0.0.1:6379> getrange key1 0 -1   # 相当于 get key 命令
"hello,world"

127.0.0.1:6379> setrange key1 6 java    # 第六个以后,开始替换指定的字符
(integer) 11
127.0.0.1:6379> get key1
"hello,javad"

setex:设置一个键值的过期时间,超过该时间后,键值自动移除
setnx:当某键值不存在时,才能设置这个键值,在分布式锁中会遇到

127.0.0.1:6379> setex key3 60 zhangsan
OK
127.0.0.1:6379> ttl key3                # 查看某个键剩余时间
(integer) 49
127.0.0.1:6379> setnx key4 lisi         # 当键值不存在时,才能设置,设置成功成功返回 1 
(integer) 1
127.0.0.1:6379> setnx key4 wangwu       # 键值存在时,设置失败,返回 0  
(integer) 0
127.0.0.1:6379> get key4          # 发现设置失败,返回的还是原 key4 值
"lisi"
127.0.0.1:6379> ttl key3         # 负数表示键值已失效
(integer) -2
127.0.0.1:6379> keys *
1) "key1"
2) "key4"

一次设置多个键值

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v11 k4 v4     # msetnx 是原子性的,一旦有一个不成功,整条语句都失败
(integer) 0
127.0.0.1:6379> get k4
(nil)

创建对象,其实就是将用户的 id 和一个属性作为键,赋予值,如
键:user:1:name,值:zhaoliu

对象:
set user:1 {name:zhaoliu,age:16}   # 设置一个 user:1 对象,json 字符串来保存一个对象
127.0.0.1:6379> mset user:1:name zhaoliu user:1:age 16
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhaoliu"
2) "16"

小进阶玩法,getset 先获取出原键的值,再将我们的新值付给这个键

##############################################################
127.0.0.1:6379> getset db mysql       # 如果不存在,返回 null
(nil)                                
127.0.0.1:6379> get db
"mysql"
127.0.0.1:6379> getset db springboot    # 如果存在值,输出原来的值,设置新的值
"mysql"                                 #输出的原键的值
127.0.0.1:6379> get db
"springboot"

List(列表)

List 列表我们可以将它当成 来理解,所有 List 的命令,都是以 l 开头,下面来看代码

127.0.0.1:6379> lpush key one            # 放到列表的头部
(integer) 1
127.0.0.1:6379> lpush key two
(integer) 2
127.0.0.1:6379> lpush key three
(integer) 3
127.0.0.1:6379> lrange key 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpush key java              # 放到列表的尾部
(integer) 4
127.0.0.1:6379> lrange key 0 -1             # 0 -1 ,获取所有值
1) "three"
2) "two"
3) "one"
4) "java"

在这里插入图片描述
弹出数据,根据键的下标获值

127.0.0.1:6379> lpop key                    # 移除列表中的第一个数据
"three"
127.0.0.1:6379> lrange key 0 -1
1) "two"
2) "one"
3) "java"
127.0.0.1:6379> rpop key                    # 移除列表中的最后一个数据
"java"
127.0.0.1:6379> lrange key 0 -1
1) "two"
2) "one" 
127.0.0.1:6379> lindex key 0               # 根据下标获取数据
"two"
127.0.0.1:6379> lindex key 1
"one"

获取元素个数,移除指定的键值

127.0.0.1:6379> lpush key one
(integer) 1
127.0.0.1:6379> lpush key two
(integer) 2
127.0.0.1:6379> lpush key three
(integer) 3
127.0.0.1:6379> lpush key three
(integer) 4
127.0.0.1:6379> lrange key 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> llen key                 #获取 List 的元素个数
(integer) 4
127.0.0.1:6379> lrem key 1 one           # 移除列表中指定的 value,精确匹配,移除 1 个
(integer) 1
127.0.0.1:6379> lrange key 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem key 2 three         # 移除列表中指定的 value,精确匹配,移除 2 个
(integer) 2
127.0.0.1:6379> lrange key 0 -1
1) "two"

根据下标,截取列表中的元素,是一个闭区间的截取

127.0.0.1:6379> rpush key one
(integer) 1
127.0.0.1:6379> rpush key two
(integer) 2
127.0.0.1:6379> rpush key three
(integer) 3
127.0.0.1:6379> rpush key four
(integer) 4
127.0.0.1:6379> lrange key 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6379> ltrim key 1 2         # 截取操作
OK
127.0.0.1:6379> lrange key 0 -1
1) "two"
2) "three"

将列表中最后一个元素弹出,放入另一个列表中

127.0.0.1:6379> lpush mylist hello1
(integer) 1
127.0.0.1:6379> lpush mylist hello2
(integer) 2
127.0.0.1:6379> lpush mylist hello3
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
127.0.0.1:6379> rpoplpush mylist otherlist   # 将 mylist 中最后一个数据弹出,放入 otherlist 中
"hello1"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello3"
2) "hello2"
127.0.0.1:6379> lrange otherlist 0 -1
1) "hello1"

替换指定位置的字符串

127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 spring         # 将第 0 位置的值更换
OK
127.0.0.1:6379> lrange list 0 0
1) "spring"

在列表某一元素 前,后 插入键值

127.0.0.1:6379> lpush list hello
(integer) 1
127.0.0.1:6379> lpush list world
(integer) 2
127.0.0.1:6379> linsert list before world 123         # 在 world 前插入 123
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "123"
2) "world"
3) "hello"
127.0.0.1:6379> linsert list after hello 987         # 在 hello 后插入987
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "123"
2) "world"
3) "hello"
4) "987"

Set(集合)

Set 是一个无序不重复集合,它的所有命令,都是以 s 开头,其命令与 List 大致相同

设置键值,获取键值,查看集合中的成员,判断集合中是否有某个成员

127.0.0.1:6379> sadd set hello
(integer) 1
127.0.0.1:6379> sadd set spring
(integer) 1
127.0.0.1:6379> sadd set maven
(integer) 1
127.0.0.1:6379> smembers set                # 查看集合中的成员
1) "maven"
2) "hello"
3) "spring"
127.0.0.1:6379> sismember set hello         # 判断集合中是否有某个元素 有返回 1 ,没有返回 0
(integer) 1
127.0.0.1:6379> sismember set last
(integer) 0

获取集合中成员的个数,删除集合中指定成员

127.0.0.1:6379> scard set                    # 获取集合中元素的个数
(integer) 3
127.0.0.1:6379> smembers set
1) "maven"
2) "hello"
3) "spring"
127.0.0.1:6379> srem set maven               # 删除集合中制定的元素
(integer) 1
127.0.0.1:6379> smembers set
1) "hello"
2) "spring"

set 是一个无序不重复集合,可以进行随机抽取,我们可以利用它做一个抽奖程序

127.0.0.1:6379> sadd set hello1
(integer) 1
127.0.0.1:6379> sadd set hello2
(integer) 1
127.0.0.1:6379> sadd set hello3
(integer) 1
127.0.0.1:6379> sadd set hello4
(integer) 1
127.0.0.1:6379> sadd set hello5
(integer) 1
127.0.0.1:6379> SRANDMEMBER set      # 随机抽取,默认抽 1 个成员
"hello4"
127.0.0.1:6379> SRANDMEMBER set
"hello2"
127.0.0.1:6379> SRANDMEMBER set
"hello2"
127.0.0.1:6379> SRANDMEMBER set
"hello4"
127.0.0.1:6379> SRANDMEMBER set
"hello1" 
127.0.0.1:6379> SRANDMEMBER set 2    # 随机抽出两个元素
1) "hello2"
2) "hello3"

随机删除一个元素

127.0.0.1:6379> spop set            # 随机弹出一个元素
"hello5"
127.0.0.1:6379> spop set
"hello4"
127.0.0.1:6379> spop set
"hello2"

将某个集合中指定的元素,移至另一集合

27.0.0.1:6379> sadd set hello1
(integer) 1
127.0.0.1:6379> sadd set hello2
(integer) 1
127.0.0.1:6379> sadd set hello3
(integer) 1
127.0.0.1:6379> sadd set2 world
(integer) 1
127.0.0.1:6379> smove set set2 hello1        # 将某个集合中的指定元素,移至另一集合
(integer) 1
127.0.0.1:6379> smembers set
1) "hello3"
2) "hello2"
127.0.0.1:6379> smembers set2
1) "hello1"
2) "world"

set 集合做 差集,交集,并集

127.0.0.1:6379> sadd set1 a
(integer) 1
127.0.0.1:6379> sadd set1 b
(integer) 1
127.0.0.1:6379> sadd set1 c
(integer) 1
127.0.0.1:6379> sadd set2 c
(integer) 1
127.0.0.1:6379> sadd set2 d
(integer) 1
127.0.0.1:6379> sadd set2 e
(integer) 1
127.0.0.1:6379> SDIFF set1 set2       # 差集 set1 中有,而 set2 中没有的
1) "a"
2) "b"
127.0.0.1:6379> SINTER set1 set2      # 交集  共同关注好友就可以这样实现
1) "c" 
127.0.0.1:6379> SUNION set1 set2      # 并集
1) "b"
2) "a"
3) "e"
4) "d"
5) "c"

Hash(哈希)

Hash,它存储的数据结构是 key - map 类型,其中 map 又是一个 k - v 键值对,并且,hash 的一个键,可以存储多个值,也就是说,hash 的一个 key 可以有多个 map
在这里插入图片描述
添加键值,批量添加键值,获取键值,批量获取键值,获取所有的键,获取所有的值
删除键值,获取键值对的个数

127.0.0.1:6379> hset myhash k1 v1             # 设置键值
(integer) 1
127.0.0.1:6379> hmset myhash k2 v2 k3 v3	  # 批量设置键值
OK
127.0.0.1:6379> hget myhash k1 				  # 获取值
"v1"
127.0.0.1:6379> hmget myhash k2 k3			  # 批量获取值
1) "v2"
2) "v3"	
127.0.0.1:6379> HGETALL myhash				  # 获取所有键值
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"
127.0.0.1:6379> hdel myhash k1                # 删除指定键
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "k2"
2) "v2"
3) "k3"
4) "v3"
127.0.0.1:6379> hlen myhash                    # 获取键值个数
(integer) 2

判断集合中是否存在某个键值,获取所有的键,获取所有的值

127.0.0.1:6379> hset myset k1 v1
(integer) 1
127.0.0.1:6379> hset myset k2 v2
(integer) 1
127.0.0.1:6379> hset myset k3 v3
(integer) 1
127.0.0.1:6379> hexists myset k1        # 判断某个值是否存在,存在返回 1,不存在返回 0
(integer) 1
127.0.0.1:6379> HEXISTS myset k8
(integer) 0
127.0.0.1:6379> HKEYS myset             # 获取所有的键
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> HVALS myset				# 获取所有的值
1) "v1"
2) "v2"
3) "v3"

map 中的值自增,如果某个键值不存在再设置

127.0.0.1:6379> hset myset k4 1
(integer) 1
127.0.0.1:6379> HINCRBY myset k4 1         # map 中的值 自增
(integer) 2
127.0.0.1:6379> hget myset k4
"2" 
127.0.0.1:6379> hsetnx myset k5 v5         # 如果不存在,可以设置
(integer) 1
127.0.0.1:6379> hsetnx myset k5 v555		# 如果存在,设置失败
(integer) 0

使用 hash 存储对象,我们将 hash 表想象成一张横着的表
在这里插入图片描述

127.0.0.1:6379> hset user1 name zhangsan
(integer) 1
127.0.0.1:6379> hset user1 age 19
(integer) 1
127.0.0.1:6379> hget user1 name
"zhangsan"
127.0.0.1:6379> hget user1 age
"19"

Zset(有序集合)

Zset 是一个有序集合,它的命令都是以 z 开头的
设置键值,获取键值

127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
127.0.0.1:6379> zrange myset 0 -1      # 获取所有键值
1) "one"
2) "two"
3) "three"

zset 既然是有序集合,那么它就能排序

127.0.0.1:6379> zadd salary 2500 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 5000 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 300 lisi
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf       # 根据 score 从小到大排序
1) "lisi"
2) "zhangsan"
3) "xiaoming"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores # 根据 score 带上值,从小到大排序
1) "lisi"
2) "300"
3) "zhangsan"
4) "2500"
5) "xiaoming"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores  # 从小到指定的值排序
1) "lisi"
2) "300"
3) "zhangsan"
4) "2500"

移除集合中的指定元素,获取集合中元素的个数

127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "zhangsan"
3) "xiaoming"
127.0.0.1:6379> zrem salary xiaoming        # 移除集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "zhangsan"
127.0.0.1:6379> zcard salary          # 获取有序集合中元素的个数
(integer) 2

获取区间中元素个数

127.0.0.1:6379> zadd set 1 one
(integer) 1
127.0.0.1:6379> zadd set 2 two
(integer) 1
127.0.0.1:6379> zadd set 3 three
(integer) 1
127.0.0.1:6379> zadd set 4 four
(integer) 1
127.0.0.1:6379> zcount set 1 2        # 获取指定区间成员的数量
(integer) 2
127.0.0.1:6379> zcount set 1 4
(integer) 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值