get和set两个命令是最基本也是最常用的命令,主要用于操作字符串类型的数据。
1.SET 命令:
SET 命令用于设置指定 key 的值。如果 key 已经持有其他值,SET 就覆写旧值,无视类型。具体的命令格式如下:
SET key value
例如,SET mykey "Hello"
将key为"mykey"的值设置为"Hello"。
2.GET 命令:
GET 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。否则,返回 key 的值。如果 key 不是字符串类型,那么返回一个错误。具体的命令格式如下:
GET key
例如,GET mykey
将获取key为"mykey"的值。
对于上述这里的key value,不需要加上引号,就是表示字符串的类型。当然,如果要是给key和value 加上引号,也是可以的(单引号或者双引号都行)
示例:
[nullptr@bogon Code]$ redis-cli
127.0.0.1:6379> set mykey "Hello,World!"
OK
127.0.0.1:6379> get mykey
"Hello,World!"
127.0.0.1:6379>
keys命令用于在Redis数据库中查找匹配给定模式的所有键。这是一个非常有用的命令,因为它允许你查找和检查Redis数据库中的键
以下是keys命令的基础语法:
KEYS pattern
在这里,“pattern”参数是一个与键匹配的模式。可以在模式中使用星号(*)作为通配符。
例如,要查找以"test"开头的所有键,你可以使用以下命令:
KEYS test*
这将会返回所有以"test"开头的键。
keys的通配样式:
时间复杂度:O(N)
返回值:匹配 pattern 的所有 key。
示例:
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> set mykey myvalue
OK
127.0.0.1:6379> keys key*
1) "key2"
2) "key1"
127.0.0.1:6379> keys *
1) "mykey"
2) "key2"
3) "key1"
需要注意的是,尽管KEYS命令可以在开发环境中进行调试和测试很有用,但是在生产环境中使用需要谨慎,因为如果数据库中包含大量的键,执行此命令可能会消耗大量的计算资源并阻塞Redis服务器。这是因为Redis是单线程的,而KEYS命令在执行时会阻塞其他的Redis操作。
对于生产环境,Redis提供了一个SCAN命令,可以用来增量地查找数据库中的键。这是一个更为安全和高效的方式来查找和操作大量的键。
判断某个key是否存在。
语法:
EXISTS key [key ...]
时间复杂度:O(1),redis组织这些key就是按照哈希表的方式来组织的
返回值:key存在的个数。
示例:
127.0.0.1:6379> exists key1
(integer) 1
127.0.0.1:6379> exists key1 key2
(integer) 2
127.0.0.1:6379>
从Redis 3.0.3版本开始,EXISTS命令才支持检查多个键。
删除指定的key
语法:
DEL key [key ...]
时间复杂度:O(1)
返回值:删除掉的key的个数。
示例:
127.0.0.1:6379> keys key*
1) "key2"
2) "key1"
127.0.0.1:6379> del key1 key2
(integer) 2
127.0.0.1:6379> keys key*
(empty list or set)
注意:在mysql数据库中删除操作是非常危险的,而在redis中需要根据场景来分析是否危险
Redis的三种主要应用场景:作为缓存、数据库和消息队列,以及在这些场景下误删数据带来的影响。
expire命令用于设置一个键的过期时间。一旦键达到过期时间,它就会被自动删除。这对于缓存失效的场景特别有用。
以下是expire
命令的基本语法:
EXPIRE key seconds
在这里,“key”参数是你想要设置过期时间的键的名称,“seconds”参数是你希望键在多少秒后过期。
例如,你可以使用以下命令来设置一个名为"mykey"的键,在60秒后过期:
expire mykey 60
如果键成功设置了过期时间,EXPIRE命令会返回1。如果键不存在或者不能设置过期时间,它将返回0。
你可以使用TTL
命令来检查一个键还有多少秒会过期:
TTL mykey
这将返回剩余的过期时间(以秒为单位)。如果键不存在或者没有设置过期时间,它将返回-1。如果键已经过期,它将返回-2。
示例:
127.0.0.1:6379> set mykey 1
OK
127.0.0.1:6379> expire mykey 60
(integer) 1
127.0.0.1:6379> TTL mykey
(integer) 54
对于计算机来说,秒是一个非常长的时间,那么如何设置更细的时间呢?
使用pexpire
命令:
pexpire key 毫秒
同时使用pttl
命令查看
一个redis 中可能同时存在很多很多key。这些key中可能有很大一部分都有过期时间.此时, redis服务器咋知道哪些key已经过期要被删除,哪些key还没过期?
在 Redis 中,有三种主要的键过期策略:
在实际运行中,Redis 同时使用了惰性删除和定期删除两种策略。当有客户端试图访问一个键时,会使用惰性删除。而定期删除则会在定时任务中进行,根据配置的策略,定时检查一定数量的随机键,删除其中已经过期的键
返回 key 对应的数据类型。
语法:
TYPE key
时间复杂度:O(1)
返回值: none , string , list , set , zset , hash and stream.
示例:
127.0.0.1:6379> set key1 value
OK
127.0.0.1:6379> lpush key2 value
(integer) 1
127.0.0.1:6379> sadd key3 value
(integer) 1
127.0.0.1:6379> type key1
string
127.0.0.1:6379> type key2
list
127.0.0.1:6379> type key3
set
type命令实际返回的就是当前键的数据结构类型,它们分别是: string (字符串)、list(列表)、hash (哈希)、set(集合)、zset(有序集合),但这些只是Redis对外的数据结构
具体如下:
实际上Redis针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样Redis会在合适的场景选择合适的内部编码
Redi五种数据类型的内部编码如下:
可以看到每种数据结构都有至少两种以上的内部编码实现,例如list数据结构包含了linkedlist和ziplist两种内部编码。同时有些内部编码,例如ziplist,可以作为多种数据结构的内部实现,可以通过object encoding命令查询内部编码:
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> object encoding hello
"embstr"
127.0.0.1:6379> object encoding mylist
"quicklist"
可以看到hello对应值的内部编码是embstr,键 mylist对应值的内部编码是ziplist
Redis这样设计有两个好处:
Redis使用了单线程架构来实现高性能的内存数据库服务,我们首先通过多个客户端命令调用的例子说明Redis单线程命令处理机制,接着分析Redis单线程模型为什么性能如此之高,最终给出为什么理解单线程模型是使用和运维Redis的关键。
现在开启了三个redis-cli客户端同时执行命令。
客户端1设置⼀个字符串键值对:
127.0.0.1:6379> set hello world
客户端2对counter做自增操作:
127.0.0.1:6379> incr counter
客户端3对 counter做自增操作:
127.0.0.1:6379> incr counter
我们已经知道从客户端发送的命令经历了︰发送命令、执行命令、返回结果三个阶段,其中我们重点关注第2步。我们所谓的Redis是采用单线程模型执行命令的是指:虽然三个客户端看起来是同时要求Redis去执行命令的,但微观角度,这些命令还是采用线性方式去执行的,只是原则上命令的执行顺序是不确定的,但一定不会有两条命令被同步执行。
宏观上同时要求服务的客户端
微观上客户端发送命令的时间有先后次序的
Redis的单线程模型
可以想象Redis内部只有一个服务窗口,多个客户端按照它们达到的先后顺序被排队在窗口前,依次接受Redis的服务,所以两条incr命令无论执行顺序,结果一定是2,不会发生并发问题,这个就是Redis的单线程执行模型。
通常来讲,单线程处理能力要比多线程差,例如有10000公斤货物,每辆车的运载能力是每次200公斤,那么要50次才能完成;但是如果有50辆车,只要安排合理,只需要依次就可以完成任务。那么为什么Redis使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:
Redis使用I/O多路复用模型
虽然单线程给Redis带来很多好处,但还是有一个致命的问题:对于单个命令的执行时间都是有要求的。如果某个命令执行过长,会导致其他命令全部处于等待队列中,迟迟等不到响应,造成客户端的阻塞,对于Redis这种高性能的服务来说是非常严重的,所以Redis是面向快速执行场景的数据库。