回顾
上一篇文章介绍了redis的一些特性和安装方式,但光说不练假把式~ 本文就来着重来介绍一下redis中的基本指令
Redis基本结构
Redis是一个客户端-服务器结构的程序(MySQL也是),客户端和服务器可以在同一台主机上,也可以不在同一台主机(本人条件有限,后续就演示在同一台主机上)。
Redis的服务器负责存储管理数据,当客户端发起一个请求的时候,服务器获取并解析,做出相应的业务操作。
Redis的客户端则是负责将用户的指令进行处理,然后通过网络通信交给服务器,而客户端的形态大致有三类:
1.命令行客户端(本文先主要讲解这个方式)
在Unbuntu上使用redis-cli即可切换~
2.图形化界面的客户端
3.基于Redis的API自行开发的客户端
补充:
Redis的快主要是相较于MySQL的,这两个都是CS结构的程序,都需要通过网络通信,但Redis操作的是内存中的数据,所以相比于MySQL就会快很多。
如果Redis是跟本机的内存相比的话,则慢很多了,网络开销不可忽略!!!
所以不能无脑使用Redis,一定要根据业务场景来使用!
Redis基本指令
由于Redis的指令非常的多,在这就先介绍一些常用的指令
1.连接Redis服务器
#此处[]中的内容可以省略
redis-cli -h [host] -p [port] [command]
通过这个指令我们就能够连接上了。
2.get和set
由于Redis是按照"键值对"的方式存储数据的,我们需要通过set,存入一个键值对,然后通过get取出。
#Demo01
set key1 value1
#这段代码表示,在内存中存储一个 key 为 "key1" value 为 "value1"
get key1
#这段代码表示从内存中取出 key 为 "key1" 的 value 的值
如果我们取get一个不存在的key,会发什么呢?
会返回nil 和null表示同一个意思~
通过观察我们可以发现,我们的key值都是String类型的,Value也都是String类型的。
key为String类型是Redis固定死的,那么如何进行插入其他类型的Value呢?(下篇再讲~)
全局命令
虽然Redis的Key都是String类型的,但Value可以支持其他类型~而针对这些不同类型的Value,操作的指令也各不相同,而全局命令则是可以适用于任何类型~
3.keys
keys用来查询当前服务器上的所有key,redis还支持一些特殊的符号(通配符)来进行匹配要查询的key。
#语法形式
keys {pattern}
#此处的pattern指定是要查询的key的样子
pattern所支持的通配符:
1.* 此处的*可以用来任意匹配0或多个字符
2.? 此处的?可以用来任意匹配1个字符
3.[abc] 此处abc表示必须匹配a或者b或者c
4.[^a] 此处表示除了a其他任意字符都可以匹配
5.[a-c] 此处表示匹配a到c之间的字符,区间为左闭右闭
举例:
#在这插入了 "hello","hallo","hbllo","heeeeeeeeello","key1" 这些key
127.0.0.1:6379> keys h?llo
1) "hbllo"
2) "hello"
3) "hallo"
127.0.0.1:6379> keys h?llo
1) "hbllo"
2) "hello"
3) "hallo"
127.0.0.1:6379> keys h[ab]llo
1) "hbllo"
2) "hallo"
127.0.0.1:6379> keys h[^ab]llo
1) "hello"
127.0.0.1:6379> keys h[a-c]llo
1) "hbllo"
2) "hallo"
注意:
keys 命令的时间复杂度为O(n).一般在生产环境(线上环境)会禁止使用 keys 命令,因为生产环境中的数据非常多,执行keys的时间就会很长,而redis服务器又是一个单线程的服务器(Redis 5之前是单线程,此处的单线程指的是Redis去内存处理指令),因此服务器就会进行阻塞,无法给其他的客户端服务,如果是使用Redis对数据库进行缓存的话,此时Redis被阻塞了,这些查询请求超时就会去访问数据库,而数据库又比较脆弱,一旦请求量大了,就挂了,整个系统也就寄了~
4.exists
exists用来判断key是否存在,返回的是key的存在的个数。
#基本语法
exsits key1 key2 ......
#判断 key1 是否存在, 判断 key2 是否存在 ......
#最后返回一个存在的个数
exists指令的时间复杂度为O(1),毕竟只需要进行查询嘛~
思考:
为什么要支持一次查询多个key是否存在,为什么不分两次进行查询呢?
理论上分开查询是可以用来判断是否存在,但是每一次查询都是一次网络通信,相较于内存来说开销比较大,毕竟每一次网络通信都需要将数据进行封装,从网卡传输出去,然后再进行分用,取出数据(类似快递的寄和拆)。
5.del
删除key,可以一次删除一个也可以删除多个,时间复杂度为O(1),返回值为删掉key的个数。
#基本语法
del key1 key2 .......
注意:
一般Redis是用作缓存的,而缓存中主要存放的是热点数据,一旦删除了,请求就会去访问数据库,如果请求量多了,数据库就有可能挂掉;如果是用Redis来当数据库,则更不能直接删除了。
因此del命令使用的时候还是需要慎重考虑的
6.expire
expire 是用来给指定的key设置过期时间,设置的单位是秒,一旦key存活的时间超过,就会进行删除,此处设定时间必须是针对已经存在了的key,如果设置成功则返回1,设置失败返回0.
#基本语法
expire key second
过期策略的实现:
Redis中可能会存在很多的Key,其中这些Key可能很大一部有一个过期时间,Redis对这些过期的Key进行删除呢?如果使用直接去遍历Key的话会非常耗时,效率比较低~
1.惰性策略
如果这个Key已经到了超时时间,但暂时还没有删除(没有被定期选中),这个Key还在,当下一次去访问这个Key的时候,发现已经过期了,Redis就触发删除操作,同时返回空值.
2.定期策略
Redis会定期选取一些Key,然后检查是否过期,但是整个过程对于时间的要求比较高,即不能耗时太多,否则就会造成阻塞。
以上是Redis采用的一些策略,显然是不够用的,后续还会继续补充。
定时器策略(没用采用)
如果使用定时器的方式来实现的话,就需要引入多线程了,但作者可能在最初设计的时候就定下了基调,就准备只采用单线程的方式。
1)基于优先级队列实现的定时器
当一个Key被设置了过期时间,就会被添加到定时器中,而此处的定时器是基于优先级队列来实现的,本质上是一个小根堆,根节点的如果没有超时,那么其他的也节点也不会超时。所以只需要去关注根节点,即使用一个扫描线程去关注根节点是否过期,而这个线程也不需要一直去询问是否过期可以设置一个等待时间,这样就可以大大剩下CPU的空闲时间了。当后续新设置了一个Key过期时间,需要唤醒一下,重新检查根节点,然后再调整等待即可。
2)基于时间轮实现的定时器
将时间分为多片,进行制定轮询的方向以及编号。后续有个过期时间进行计算,存储到对应的时间片上,这个一片上存储了多个任务节点。时间轮没一次轮询就会去检查当前时间片上的任务节点是否已经过期然后删除。
7.ttl
ttl类似网络原理中的IP协议中的字段TTL(表示转发的次数),用来表示key的过期时间还剩余多少秒.
#基本语法
ttl key
8.type
type是用来返回Key对应的Value的类型
#基本语法
type key
最后
下一篇会对Redis的数据类型进行讲解,并对不同类型的指令进行补充。