气势凌人的茶叶 · 杭州市热门民办小学学费统计· 1 月前 · |
谦和的马克杯 · JavaScript 物件基礎概念 - ...· 1 月前 · |
被表白的橙子 · PHPExcel导出网络图片_php ...· 2 月前 · |
玩命的牛肉面 · 历届中国乒乓球公开赛冠军榜 ...· 2 月前 · |
踏实的移动电源 · 如何在React ...· 4 月前 · |
这篇文章我们主要是想介绍
Redis
的使用,现在开发中
Redis
是使用的非常频繁的,一般都是作为缓存来使用,进而减小用户请求对数据库的压力,这样就能使系统运行更加稳定,其实
Redis
数据库中保存的就是比较固定的数据,比如用户的信息,当有请求想要访问某个用户的信息时,就可以直接从
Redis
缓存中获取得到了,而不用每次都去查询数据库了,这样数据库的压力就减轻了,同时当用户信息有修改时,我们也同时修改
Redis
缓存中的信息,这样的话就相当于对系统中数据的存储进行了优化。
1.支持数据的持久化。数据不仅可以保存在内存中,同时也可以保存在磁盘中,并且可以进行交互。
2.不仅支持保存简单的字符串string格式的数据,还支持list、set、zset、hash等多种格式的数据。
3.支持数据的备份。也就是主从模式的备份。
同时,
Redis
相对于其它的缓存数据库来说,还具有以下优势:
1.性能好。读写速度都非常快。
2.丰富的数据类型。也就是我们上面所提到的5种数据类型。
3.原子性操作。Redis中所有的操作都是原子性的,而且还支持几个操作合并后的原子性执行。
4.丰富的特性。Redis还支持publish/subscribe,通知以及key过期等高级特性。
wget http://download.redis.io/releases/redis-3.2.8.tar.gz
这样的话,同样也是可以进行下载操作的,不过需要保证是有网络环境的,这样操作之后,我们的安装包就下载好了,这里我们使用
Redis
的版本为
3.2.8
的,还需要说明的一点就是,
Redis
数据库原生是只支持
Linux
系统的,不支持
Windows
系统的,所以
Windows
版本的
Redis
数据库是微软自己建立的分支,当然是根据
Redis
官方的源码进行编译、发布和维护的,这样的话,
Windows
版本的
Redis
版本就总是低于
Linux
版本的,但是使用起来是没有什么区别的。
下面我们就来看如何进行安装操作,之前我们已经得到了
Redis
数据库的安装包,也就是
redis-3.2.8.tar.gz
的安装包,我们在
Linux
系统中安装软件时一般都会将其安装到
/usr/local
目录下,因此我们可以先将
Redis
数据库的安装包上传到该目录,然后我们就可以进行安装操作了,第一步便是解压安装包了,我们可以使用
tar -zxvf redis-3.2.8.tar.gz
命令进行解压缩包操作,执行完解压操作之后,就可以在同一级目录中看到有一个
redis-3.2.8
目录,当然就是我们压缩包解压出来的了,那接下来就是第二步的操作了,因为
redis-3.2.8
目录中的都是
Redis
数据库的源码,所以我们需要对该源码进行编译和安装操作,第二步我们便是进行编译操作,首先需要进入到
redis-3.2.8
目录,然后执行
make
命令就行了,这个命令便是进行编译源码操作的,这里需要注意的一点是,这里由于系统环境的原因可能会报错,如:
/bin/sh: cc: command not found
这个报错是因为当前
Linux
系统中缺少
gcc
环境的原因,所以我们需要先安装
gcc
环境,安装方式为:
yum install gcc
这样我们安装了
gcc
环境之后,再执行
make
命令进行源码编译就是可以的了,执行了编译操作之后,下面就是最后一步安装操作了,即将我们的
Redis
安装到指定的目录当中,当然还是在
redis-3.2.8
目录当中,执行如下命令:
make PREFIX=/usr/local/redis install
这个命令便是将
Redis
安装到
/usr/local/redis
这个目录当中,但是因为现在
/usr/local
目录是没有
redis
目录的,所以需要先去新建这个目录,然后再执行上面的安装操作,操作完成之后就安装完成了,这便是第三步安装操作,这样的话,
Redis
数据库的安装便完成了。
下面我们就可以到
Redis
数据库的安装目录
/usr/local/redis
目录进行查看了,会发现其中有一个
bin
目录,进入该
bin
目录,会发现有几个文件,我们一个一个进行说明。
redis-server:Redis服务器
redis-cli:Redis命令行客户端
redis-benchmark:Redis性能检测工具
redis-check-aof:AOF文件修复工具
redis-check-rdb:RDB文件修复工具
安装好
Redis
服务器之后,我们可以启动服务然后测试是否可以正常使用的,启动的方式十分简单,可以直接到
redis
目录,然后再到
bin
目录,直接执行
./redis-server
命令,这时候我们就可以看到日志提示
Redis
数据库正常启动了,这种方式在测试时可以使用,但是在实际使用中一般不会这样,在实际使用中我们通常会使用配置文件的方式启动服务,配置文件就是
redis-3.2.8
目录中的
redis.conf
文件,我们可以先进入到
redis-3.2.8
目录,然后使用下面的命令将配置文件拷贝到
Redis
的安装目录中。
cp redis.conf /usr/local/redis
复制好文件之后,我们就可以回到
redis
目录中启动
Redis
数据库了,执行命令为:
./bin/redis-server ./redis.conf
通过控制台打印的日志我们就能看到启动好了,也就是
Redis
数据库的服务端启动好了,然后下面我们还需要启动
Redis
数据库的命令行客户端,这样就便于我们进行测试,启动命令行客户端也十分简单,只需要进入到
bin
目录,然后执行
./redis-cli
命令就好了,当然执行这种命令的话,就是默认连接本地的
Redis
数据库了,那如果想要连接指定
IP
和端口的服务器呢,就可以使用类似下面的命令了。
./redis-cli -h 127.0.0.1 -p 6379
上面的命令就是指定连接本地主机端口号为
6379
的
Redis
数据库了,连接成功后,我们便可以使用
Redis
数据库了,我们可以输入一个
ping
命令进行测试,这时候会返回一个
PONG
,这就表示
Redis
数据库安装是正常的了。
需要说明的一点是,当
Redis
数据库启动时默认是只能在本机进行访问的,也就是别的主机是访问不了的,这是在
Redis
的配置文件
redis.conf
中进行设置的,配置为
bind 127.0.0.1
,也就是为
Redis
数据库绑定的
IP
地址为
127.0.0.1
,然后我们看这个配置上面的说明的话,就可以看到,之所以默认设置为只能本机访问,是出于安全考虑。
Redis
数据库提供了丰富的数据类型供我们使用,一共有
5
种数据类型,分别为:
string:普通字符串
list:链表
set:集合
zset:有序集合(sorted set)
hash:哈希
下面我们就分别针对这五种数据类型分别进行说明,看看它们各自都有什么方法供我们使用。
set key value
这个
set
命令便是用来设置键值对的,即设置
key
所对应的值为
value
,如果这个
key
已经存在了,则会覆盖这个
key
所对应的原来的
value
值。比如可以这样使用:
set name kobe
上面这个命令便是设置
name
这个键所对应的值为
kobe
,那如果想要获取到某个键对应的值呢?那就可以使用与上面这个
set
命令相对应的
get
命令了,使用
get
命令我们便可以获取
key
所对应的
value
值了。
get key
这个
get
命令便是用来获取键所对应的值的,如果
key
在
Redis
数据库中不存在的话,则会返回
nil
,表示该
key
不存在,并且该
key
所对应的
value
也不存在。
mset key value [key value...]
这个
mset
命令是用来设置多个键值对的,和
set
命令相同的,当对应的
key
已经存在时,这个命令同样也会覆盖
key
所对应的
value
值,所以这个命令完全可以看成是
set
命令的多次迭代操作。具体的使用则可以如下:
mset age 18 sex boy
这里便是设置了两组键值对,一组为年龄,另一组则为性别,
key
为
age
所对应的
value
为
18
,而
key
为
sex
所对应的
value
则为
boy
,这样就完成了设置多组键值对的操作。有设置多个键值对的命令,当然也有对应的根据多个键获取对应值的操作了,也就是
mget
命令了。
mget key [key...]
这个
mget
命令就是根据多个键获取得到对应的值了,当有的
key
不存在时,则会返回
nil
,因此
mget
可以完全看作是
get
命令的多次迭代操作,例如我们可以这样使用:
mget sex age
,这样的话我们就能获取得到
sex
和
age
这两个键所对应的
value
了。
setnx key value
这个
setnx
命令同样也是用来设置某个键所对应的值的,但是它比较特别的地方在于,当这个
key
不存在时,
setnx
命令的效果和
set
命令是一样的,都是设置这个
key
所对应的
value
,并且此时的返回值为
1
,但是当命令中设置的
key
已经在
Redis
中存在时,那么这时候不会做任何操作,这时的返回值为
0
。具体的使用可以如下:
setnx age 19
setnx birth 2019-01-18
第一个命令是来设置
age
这个
key
对应的
value
值为
19
的,但是之前我们已经设置过
age
对应的
value
为
18
,因此这里使用
setnx
命令不会修改
age
所对应的
value
值,而且此时的返回值也为
0
;再看第二个命令,是设置
birth
这个
key
的,因为我们之前是没有设置过这个
key
的,因此此时是可以设置成功的,返回值也应该为
1
。
msetnx key value [key value...]
这个
msetnx
命令是原子性的完成参数中所有
key/value
的设置操作,相当于是循环迭代的
setnx
命令,有一点需要注意的就是,如果命令中的某个
key
已经存在了,那么该命令所有的操作都会回滚,也就是全部的操作都会失效,返回值为
0
,具体的使用可以如下:
msetnx age 10 like basketball
在上面这个命令中,由于我们之前已经设置过
key
为
age
的键值对,因此在这里再次设置时是不会生效的,而且由于该命令具有原子性的特点,因此命令中所有的键值对设置都不会生效。
append key value
这个
append
命令是用来追加某个
key
所对应的
value
值的,当命令中的
key
已经存在时,那这个命令就会将命令中的
value
追加到命令中
key
所对应
value
的后面,如果命令中的
key
在
Redis
数据库还不存在的话,那么就相当于是一次设置操作,具体的使用可以如下:
append name ' is a boy'
因为在之前的命令中,我们已经设置
name
这个
key
所对应的
value
为
kobe
了,然后在这里再使用
append
追加命令,那么现在
name
这个
key
所对应的
value
就应该是
kobe is a boy
了,当然我们是可以使用
get name
这个命令来进行验证的。
decr key
这个
decr
命令是将
key
所对应的
value
值递减
1
,当然这时候就必须要求这个
key
所对应的
value
必须是能转换成整形值的数据了,否则就会报错了,同时,如果命令中的
key
不存在的话,那么就会默认这个
key
所对应的
value
为
0
,然后再进行递减
1
的操作,返回的就是
-1
了,其实这里的
key
如果不存在的话,就相当于是先设置该
key
所对应的
value
值为
0
了,然后再进行的递减操作。具体使用可以如下:
decr age
由于之前我们已经将
age
这个
key
所对应的
value
设置为
18
了,然后这里
decr
命令的结果就会返回
17
了。
incr key
这个
incr
命令的效果便是和上面
decr
命令的效果是相对的,也就是将
key
所对应的
value
递增
1
,同样也要求
key
所对应的
value
值是能转换成整形值的数据,当命令中的
key
在
Redis
中不存在时,会先设置该
key
所对应的
value
为
0
,然后再进行递增
1
的操作,这时候就会返回
1
了,具体的使用如下:
incr age
因为之前的操作,
Redis
数据库中
age
对应的
value
应该是
17
了,而这里使用
incr
命令的话就会返回
18
了。
decrby key decrement
这个
decrby
命令的作用和
decr
命令的作用是一样的,也是将命令中
key
所对应的
value
值进行减操作,只不过
decr
命令每次都是确定的减
1
,而
decrby
命令则可以根据命令中的参数减少指定的数据,不过有一点是相同的,那就是当命令中的
key
不存在时,
Redis
会先指定该
key
对应的
value
值为
0
,然后再进行减操作。具体的使用可以如下:
decrby count 4
这里因为之前在
Redis
中是不存在
count
这个
key
的,所以返回的应该是
-4
。
incrby key increment
这个命令则是和上面的
decrby
命令相对应的,
incrby
命令主要是用来对某个
key
所对应的
value
值进行增加操作,同样可以指定所增加值的大小,并且当
key
不存在时,也会先将
key
所对应的
value
置为
0
,具体使用可以如下:
incrby count 5
由于之前
count
所对应的值已经设为
-4
了,在这里进行加
5
的操作,那最后返回的结果就应该是
1
了。
getset key value
这个
getset
命令同样也是用来设置键值对的,作用的效果其实和
set
命令是一样的,不过有一点区别的就是,
getset
命令不仅会设置键值对,而且还会返回这个
key
所对应的原来
value
值,具体使用可以如下:
getset age 16
因为之前
age
这个
key
所对应的
value
是
18
,所以执行上面这个命令时,就会将
age
这个
key
所对应的
value
设置为
16
,同时也会返回原来的对应值
18
。
strlen key
这个
strlen
命令则是用来返回
key
所对应
value
值的长度,我们可以直接使用:
strlen name
由于之前
name
这个
key
所对应的
value
值为
kobe is a boy
,因此这里的返回值应该是
13
。
setex key seconds value
这个
setex
命令主要是用来设置键值对,同时设置键的生命周期的,也就是这个
key
在
Redis
中存在的时长,之前我们使用
set
命令设置的键值对,其生命周期都是永久的,在实际开发中我们一般都会指定
key
的生命周期,这样就不会使
Redis
中的
key
过多。具体的使用可以如下:
setex age 10 6
上面这个命令的作用就是设置
age
这个
key
所对应的
value
值为
6
,并且该
key
的存活时间为
10
秒钟,我们这里如果想要查看某个
key
的生命周期的话,是可以使用
ttl
命令的,比如
ttl age
命令,便是查看
age
这个
key
的生命周期了,我们之前使用
set
命令设置的键值对,其生命周期为永远,这时候使用
ttl
命令返回的就是
-1
了。
setrange key offset value
这个
setrange
命令主要是用来对
key
所对应的
value
值进行局部替换操作,替换的位置就是
offset
了,替换的值也就是命令中的
value
值了,当命令中的
offset
值大于
key
所对应
value
的长度时,那就会在原
value
值和
offset
之间插入
\u0000
值,在我们之前的操作中,
name
这个
key
所对应的
value
值应该是
kobe is a boy
,我们现在如果使用下面这个命令的话:
setrange name 10 girl
那这时候,
name
这个
key
所对应的
value
值就应该是
kobe is a girl
了。同时,如果命令中的
key
是不存在的话,那就会直接为该
key
进行设置操作了,并且如果该命令中的
offset
大于
0
的话,同样的也会在
offset
位置之前插入
\u0000
字符的。
getrange key start end
这个
getrange
命令则是用来获取
key
所对应
value
中的某部分值的,命令中的
start
和
end
则是表示获取数据的区间,这里的区间是闭区间,也就是说获取
value
值上面的第
start
个元素到
end
个元素时,
start
和
end
位置上面的元素都会包含在内,比如我们可以如下进行使用:
getrange name 0 1
那上面这个命令就会返回
ko
了,当然,如果想要获取得到
key
所对应的
value
完整值的话,其实是可以使用这个命令的,
getrange name 0 -1
,
0
表示的是从第
1
位开始,
-1
则是表示到最后一位。
getbit key offset
这个
getbit
命令是用来获取
key
所对应
value
值二进制位的,每个二进制位只可能是
0
或者
1
,这里就需要说一下十进制数和字母如何用二进制进行表示了,比如十进制数
1
,如果用
8
位二进制表示的话,那就应该是
0000 0001
了,其实所有的十进制数都可以使用二进制来表示的,那字母呢?其实也是可以的,这里就需要使用
ASCII
码表了,这张表上面就列出了字母所表示的十进制数以及二进制数,比如
a
,它的十进制表示就是
97
,二进制表示就是
0110 0001
了,而
A
的话,它的十进制表示就是
65
,二进制表示则是
0100 0001
了,如果我们先设置一个
key
所对应的
value
为
a
,那再获取得到它每一个二进制位上面的数据,就可以看到该
value
的二进制表示了。
> set key a
> get key
> getbit key 0
> getbit key 1
> getbit key 2
> getbit key 3
> getbit key 4
> getbit key 5
> getbit key 6
> getbit key 7
上面我们得到的结果其实依次来看的话,就是
0110 0001
了,和我们上面说的
a
的二进制表示是一致的。
setbit key offset value
这个
setbit
命令是用来设置
key
所对应
value
上的二进制位的,其实理解了上面的
getbit
命令,那这个
setbit
命令也就很好理解了,因为这两个命令刚好也是相对的,
setbit
命令刚好就是用来修改
value
上面某个二进制位上面的值的,如果想看到效果的话,那我们可以直接对上面的
key
所对应的
a
这个
value
进行修改,
a
所对应的二进制为
0110 0001
,而
A
所对应的二进制为
0100 0001
,两者的二进制表示主要就是第
3
个二进制位的差别,那我们可以执行下面的命令:
setbit key 2 0
也就是将原
value
值的二进制表示第
3
位上面的数值改为
0
,那这样的话,现在
key
所对应的
value
值就是
A
了。
lpush key value [value...]
这个
lpush
命令主要是向链表中插入一个或多个元素,当命令中的
key
还不存在时,则会新建该
key
,也就是一个链表了,需要注意一下的就是,往链表中插入元素时,先插入的元素是在链表尾的,后插入的元素则是在链表头部的,下面看具体的使用:
lpush lkey01 1 2 3 4 5
上面这个命令则是向
lkey01
这个链表中插入了
5
个元素,由于在
Redis
数据库中
lkey01
这个链表是不存在的,因此在这里会先创建该链表,然后再往里面插入元素。
lpushx key value [value...]
这个
lpushx
命令同样也是往链表中插入元素的,只是有一点不一样的地方,就是当命令中
key
已经存在时,那么使用
lpushx
命令插入元素是和
lpush
命令一样的,但是如果命令中的
key
不存在,那么插入元素的操作就不会执行,因此如果想要使用
lpushx
插入元素时则必须保证链表已经是存在的了,下面看具体的使用:
lpushx lkey01 10
上面这个命令就是向
lkey01
链表又插入了一个元素
10
,如果是还不存在的链表的话,那就不会进行插入操作了。
lrange key start end
这个
lrange
命令主要是用来查看链表中的元素的,
start
和
end
就是元素所在的位置了,都是以
0
为开始计数的,同样的,查询区间也是闭区间,即
start
和
end
位置上面的元素都会被查出来,而
-1
的话则是表示最后一个位置,以此类推,
-2
则是表示倒数第二个位置,所以当我们想查询链表中全部的元素时,就可以使用如下的命令:
lrange lkey01 0 -1
上面便可以查询出链表中所有的元素来了。
lpop key
这个
lpop
命令主要是从链表中取出头部元素,如果链表不存在的话,就会返回
nil
,因此当我们想要从链表中取得头部元素时就可以使用该命令了,具体使用可以如下:
lpop lkey01
这里便是取出
lkey01
这个链表中的头部元素了,很显然这里取出的就应该是
10
这个元素了。
llen key
这个
llen
命令则是用来获取链表的长度了,也就是链表中元素的个数,当链表还不存在时,就会返回
0
,已经存在的话则会返回链表实际长度,具体使用可以如下:
llen lkey01
这里返回的值就是
5
了,因为现在链表中还有
5
个元素。
lrem key count value
这个
lrem
命令主要是用来删除链表中元素的,即删除链表中
count
个值为
value
的元素,当
count
的值大于
0
,则是表示依次从头到尾进行删除,当
count
的值小于
0
时,则表示依次从尾到头进行删除,当
count
的值等于
0
时,则表示删除链表中所有值为
value
的元素。
lset key index value
这个
lset
命令主要是用来设置链表中某个位置上面的元素值的,我们就可以用来进行替换操作了,索引值
index
是从
0
开始的,当命令中的
index
大于链表的实际长度时,就会报索引越界错误了,如果我们想设置链表中第一个元素为
100
,则可以使用如下命令:
lset lkey01 0 100
这样的话,
lkey01
链表的头部元素就会被设置为
100
。
lindex key index
这个
lindex
命令主要是返回链表中某个位置的元素值,我们便可以根据这个命令做查询相关的操作了,命令中的
index
同样是以
0
为开始的,
0
表示的是链表的头部元素所在位置,
-1
则是表示链表中尾部元素所在的位置,如果我们想获取到链表中的头部元素,那就可以这样:
lindex lkey01 0
这样的话便能得到链表的头部元素了,结合上面的
lset
命令来看的话,这里获得的元素应该是
100
了。
ltrim key start end
这个
ltrim
命令主要是用来将链表中的元素截取一部分然后保存下来,
start
和
end
则是表示保留链表中元素所在位置的区间了,
start
和
end
都是以
0
为开始的,并且区间也是闭区间,即
start
和
end
所在位置的元素都会包含在内。
linsert key before|after pivot value
这个
linsert
命令主要是用来向链表中插入元素的,即向链表中元素值为
pivot
的元素前面或者后面插入值为
value
的元素,命令中的
before
和
after
就是指定是在元素前面还是后面进行插入了。
rpush key value [value...]
前面我们介绍的往链表中插入元素和取出一个元素,都是在链表头部进行操作的,其实我们同样也是可以在链表尾部进行这样的操作的,比如这个
rpush
命令,则是向链表尾部插入元素,同样的,如果命令中的链表还不存在,则先创建该链表然后再在尾部进行插入操作。
rpushx key value
这个
rpushx
命令同样也是在链表的尾部进行插入操作,和
lpushx
类似的,这个
rpushx
只有当链表已经存在时才会进行插入操作,如果链表不存在就不会做任何操作。
rpop key
这个
rpop
命令主要是在链表尾部取出一个元素,也就是尾部元素了。
rpoplpush source destination
这个
rpoplpush
命令是作用于两个链表的,即将
source
链表的尾部元素弹出,然后插入到
destination
链表的头部,如果
source
链表不存在,则只会返回
nil
,而不会做其它操作了,如果
source
链表和
destination
链表是同一个链表,那就相当于是将这个链表的尾部元素弹出然后插入到头部了。
hset key field value
这个
hset
命令主要是用来设置一个
hash
类型的数据,当命令中的
key
不存在时,便会执行新增操作,命令中的
field
参数则是
key
所对应
Map
类型数据中的键,
value
则是
key
所对应
Map
类型数据中的值,下面通过具体的命令来学习。
hset user username tom
上面这个命令则是设置了一个
hash
类型的数据,该数据的
key
则为
user
,该
key
所对应的则是一个
Map
集合,现在该
Map
中有一对键值对,键为
username
,值则为
tom
。
hget key field
hget
命令则是用来获取
key
所对应
hash
类型数据中
field
所对应的值的,显然它的作用便是和
hset
是相对的,实际使用可以如下:
hget user username
这样的话,我们就能获得
user
这个
key
所对应
hash
类型数据中
username
这个键所对应的值了,很显然,这个值就是
tom
了。
hsetnx key field value
hsetnx
这个命令也是用来设置命令中
key
所对应的
hash
类型数据的,只不过和
hset
命令有区别的是,只有当命令中的
key
或者
field
不存在的时候,命令才会起作用,否则是不会起作用的,使用可以如下:
hsetnx user age 20
由于之前
user
所对应的
hash
类型数据中是不存在
age
这个键的,因此上面的命令便是相当于对
user
这个
key
所对应的
hash
类型数据的一次设置操作,设置其中
age
这个键所对应的值为
20
。当然如果使用下面这个命令的话那就没有用了:
hsetnx user username jerry
由于
user
这个
key
所对应的
hash
类型数据中之前就已经有了
username
这个键,因此再对这个键进行设置时,就不会再起作用了。
hexists key field
hexists
命令主要是用来判断
key
所对应的
hash
类型数据中是否包含
field
这个键,如果包含的话就会返回
1
,不包含或者连
user
这个
key
都不存在的话就会返回
0
了。具体使用可以如下:
hexists user username
上面这个命令则是用来判断
user
这个
key
所对应的
hash
类型数据中是否包含
username
这个键,很显然是包含的,因此会返回
1
。
hlen key
hlen
命令是用来确定
key
所对应的
hash
类型数据中包含
field
的个数,如果
key
不存在的话,则会返回
0
。具体使用可以如下:
hlen user
上面这个命令则是为了确定
user
这个
key
所对应
hash
类型数据中
field
的个数,很显然现在
user
所对应
hash
类型数据中包含的
field
有
username
和
age
这两个,因此上面命令的返回值为
2
。
hdel key field [field...]
hdel
命令是用来删除
key
所对应
hash
类型数据中对应的
field
,当命令中的
field
不存在时,则会忽略该
field
,具体使用可以如下:
hdel user age
上面的命令则是用来删除
user
这个
key
所对应的
hash
类型数据中的
age
这个
field
,当然在我们之前的操作中,
age
这个
field
是存在的,因此在这里的删除操作也是可以进行的。
hincrby key field increment
hincrby
命令是用来对
key
所对应
hash
类型数据中
field
所对应值进行增减操作的命令,当然这就必须要保证
field
对应的值必须是可以被转换为整数型值的,当命令中的
key
或者
field
不存在时,就会新建命令中的
key
或者
field
,并将
field
所对应的值设为
0
,然后再进行加减操作。具体使用可以如下:
hincrby user age 10
上面这个命令便是对
user
这个
key
所对应的
hash
类型数据中的
age
这个
field
对应的值进行加
10
操作,由于之前已经不存在
age
这个
field
了,因此这里
age
所对应的值先设置为
0
,然后再进行加
10
操作,最后返回的就是
10
了。
hgetall key
hgetall
命令是用来获取
key
所对应
hash
类型数据中所有的
field
以及
field
所对应的值的,相当于是对
key
所对应
hash
类型数据的遍历,具体使用可以如下:
hgetall user
上面的命令便是获取
user
这个
key
所对应
hash
类型数据中所有的数据了,包括
field
以及其所对应的值。
hkeys key
hkeys
命令是用来获取
key
所对应
hash
类型数据中所有的
field
,类似于
Java
中获取
Map
集合中所有的
key
,因此还是很好理解的,具体使用可以如下:
hkeys user
上面命令是用来获取
user
这个
key
所对应
hash
类型数据中所有
field
,根据现在的情况,返回的就应该是
username
和
age
这两个
field
了。
hvals key
hvals
命令是用来获取
key
所对应
hash
类型数据中所有
field
所对应的值的,相当于是
Java
中获取
Map
集合中的所有
value
值,该命令的具体使用如下:
hvals user
上面的命令是用来获取
user
这个
key
所对应
hash
类型数据中所有
field
所对应的值的。
hmget key field [field...]
hmget
命令是用来获取
key
所对应
hash
类型数据中多个
field
所对应的值的,如果命令中
field
不存在,返回的就是
nil
了,如果命令中的
key
都不存在,那返回的就是一组
nil
了。具体使用可以如下:
hmget user username age
上面这个命令是用来获取
user
这个
key
所对应
hash
类型数据中
username
和
age
这两个
field
所对应的值的。
hmset key field value [field value...]
hmset
命令是用来设置
key
所对应
hash
类型数据中多个
field
所对应的值的,这个的作用当然就是刚好和
hmget
命令是相对的了,具体的使用可以如下:
hmset user addr hubei birth 2019-01-01
上面命令的作用便是设置
user
这个
key
所对应的
hash
类型数据中
addr
这个
field
所对应的值为
hubei
,
birth
这个
field
所对应的值为
2019-01-01
。
sadd key member [member...]
sadd
命令相当于是往
key
这个集合中添加元素,当命令中的元素在集合中已经存在时,我们会忽略该元素,而其它的元素仍会添加成功,具体使用可以如下:
sadd set a b c d
上面命令就是往集合
set
中添加
4
个元素了,同时
4
个元素之间是无需排列的。
scard key
scard
命令则是用来获取集合中元素的个数,当集合还不存在时会返回
0
,否则就是返回实际元素个数了。具体使用可以如下:
scard set
上面这个命令便是获取
set
这个集合中元素个数了,很明显这里是有
4
个元素的,所以应该返回
4
。
sismember key member
sismember
命令则是用来判断某个元素是否是属于某个集合的,返回值
1
表示存在,而
0
则是表示不存在。具体使用可以如下:
sismember set a
上面命令则是判断
a
这个元素是否在
set
这个集合当中,很显然是在集合当中的,因此应该返回
1
。
smembers key
smembers
命令是用来查看集合中所有元素的,也就相当于是对集合的遍历了。具体使用可以如下:
smembers set
上面这个命令便是查看
set
集合中的所有元素。
spop key
spop
命令是从
key
集合中返回并删除一个元素,由于集合中元素是无序排列的,因此每次返回并删除都相当于是随机的。具体使用可以如下:
spop set
上面命令就会从
set
集合中随机返回并删除一个元素。
srandmember key
srandmember
命令是随机返回集合中的某个元素,与
spop
不一样的是,
srandmember
命令只会返回元素,而不会将元素从集合中删除。具体使用可以如下:
srandmember set
上面命令就是从集合中随机返回一个元素,因为集合中元素是排列无序的,因此每次返回的元素也是随机的。
srem key member [member...]
srem
命令主要是用来删除集合中指定元素的,如果命令中的元素在集合中不存在,则会忽略该元素。具体使用可以如下:
srem set a c
上面命令则是从集合中删除
a
和
c
这两个元素。
smove source destination member
smove
命令是用于将
source
集合中的元素移到
destination
集合当中,也就是源集合和目标集合了,假如
set
集合中的元素为
a
,
b
,
c
,而
set2
集合中元素为
1
,
2
,
3
,当我们想把
a
元素从
set
集合移到
set2
集合时,我们就可以使用下面这个命令:
smove set set2 a
这样的话我们就可以达到我们想要的效果了,即将
a
元素从
set
集合移动到
set2
集合了。
sdiff key [key...]
sdiff
命令是用来获取第一个集合与其后所有集合的差集的,为了便于说明,我们假定有两个集合,
set
与
set2
,
set
中元素为
1
,
2
,
3
,
4
,
5
,而
set2
中元素为
4
,
5
,
6
,
7
,
8
,当我们想求两个集合的差集时,则可以使用如下命令:
sdiff set set2
通过上面的命令,我们就得到了
set
集合与
set2
集合的差集了,很明显我们这里的结果就是
1
,
2
,
3
了。
sdiffstore destination key [key...]
sdiffstore
命令同样也是用来计算集合之间的差集的,只不过和
sdiff
命令之间的差别在于,
sdiffstore
命令会将集合之间的差集保存在
destination
集合当中,也就是目标集合当中,而
sdiff
命令不会,因此上面同样的两个集合求差集,也可以使用下面这个命令:
sdiffstore sdiffset set set2
上面这个命令会将两个集合之间求差集的结果保存到
sdiffset
集合当中,保存的元素也就是
1
,
2
,
3
了。
sinter key [key...]
sinter
命令则是用来求第一个集合与其后所有集合之间的交集的,这样来看的话,当命令中有一个集合为空集合或者集合不存在的话,那我们运算的结果也就是空集合了。这里我们还是求
set
和
set2
这两个集合之间的交集,命令如下:
sinter set set2
经过上面的命令,我们便能得到
set
和
set2
集合之间的交集了,很明显这里我们得到的结果应该是
4
,
5
。
sinterstore destination key [key...]
sinterstore
命令也是用来计算第一个集合与其后所有集合之间的交集的,与
sinter
命令稍微有点不同的是,
sinterstore
命令会将交集计算的结果保存在
destination
集合中,也就是目标集合中,而
sinter
命令则是将交集计算的结果直接返回。如果要计算
set
和
set2
这两个集合之间的交集的话,那我们就还可以使用下面的命令:
sinterstore sinterset set set2
上面这个命令则是将两个集合的交集结果保存到
sinterset
集合当中了,很显然其中就是
4
和
5
这两个元素了。
sunion key [key...]
sunion
命令则是用来获取第一个集合与其后所有集合之间的并集,为了便于演示,我们还是使用
set
和
set2
这两个集合,以求它们的并集:
sunion set set2
上面这个命令便是求
set
集合和
set2
集合之间的并集了,很明显可以看出结果就是
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
。
sunionstore destination key [key...]
sunionstore
命令同样也是用来求两个集合之间的并集的,同样的,与
sunion
命令不同的地方就还是在于,
sunionstore
命令会将集合之间并集运算的结果保存到
destination
集合中,也就是目标集合当中,而
sunion
命令则是直接返回结果,具体使用如下:
sunionstore sunionset set set2
上面命令则是将
set
集合和
set2
集合并集的结果保存在
destination
集合之中了,很明显其中集合元素也是
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
。
zadd key score member [score member...]
zadd
命令的作用就是往集合中添加元素了,只不过在添加元素时也会指定元素所对应的分数,这样集合中元素就能根据分数大小进行排序了,如果命令中的元素在集合中已经存在了,那这时就会根据命令中元素对应的分数对集合中元素对应的分数进行更新,同时调整集合中元素的排序。下面看具体的使用:
zadd zset 1 a 2 b 3 c 4 d 5 e
这样我们就创建了一个新的有序集合
zset
,并往其中添加了
5
个元素,并指定了
5
个元素所对应的分数是多少。
zincrby key increment member
zincrby
命令的作用主要是调整集合中元素所对应的分数,当命令中的元素在集合中并不存在时,我们就会新增该元素到集合之中,并指定该元素所对应的分数为命令中的分数参数,具体使用可以如下:
zincrby zset 2 d
上面的命令就是将集合中的
d
元素所对应的分数增加了
2
,从而也就改变了元素之间的排序序列。
zcard key
zcard
命令则是用来获取集合中的元素个数的,具体使用可以如下:
zcard zset
上面这个命令就是用来获取
zset
集合中元素个数了,很明显这里会返回
5
。
zcount key min max
zcount
命令同样也是用来获取集合中元素数量的,只不过它获取的是分数在
min
和
max
之间元素的个数,需要注意的是在默认情况下这个区间是闭区间,也就是两边都是包含的,如果想表示开区间的话,则可以使用
(
符号,如
zcount key (min (max
,这样的话就是表示分数在最小值和最大值之间的元素个数是多少了,当然如果只想表示单个闭区间也是可以的,总结起来的话就是哪一边想表示开区间的话哪一边就需要加上
(
符号。下面看具体使用:
zcount zset 2 4
上面这个命令就是得到分数大于等于
2
并小于等于
4
之间的元素个数。
zrange key start stop [withscores]
zrange
命令是用来根据索引范围获取元素的,命令中的
start
和
stop
都是表示元素在集合之中的索引区间,这里的索引都是从
0
开始的,
0
表示的是第一个元素,
-1
则是表示的最后一个元素,因此总的来说就相当于是获取某个索引区间之中的元素,需要注意的一点是,命令中还有一个可选参数
withscore
,表示的是返回元素时是否带上元素所对应的分数,存在该参数时就会带上元素所对应的分数,下面看具体的使用:
zrange zset 0 -1 withscore
上面的命令则是表示获取集合中所有的元素以及它们各自所对应的分数。
zrevrange key start stop [withscores]
zrevrange
命令同样也是根据索引获取集合中的元素以及元素所对应的分数的,和
zrange
命令唯一的区别就是
zrevrange
命令是将元素进行倒序排列,即根据元素所对应的分数按从大到小进行排列的,具体使用可以如下:
zrevrange zset 0 -1 withscores
上面这个命令同样也是获取
zset
集合中元素以及元素对应分数的,只不过和上面使用
zrange
命令不一样的是,这里所得到的元素排列顺序是和
zrange
命令刚好相反的。
zrangebyscore key min max [withscores] [limit offset count]
zrangebyscore
命令的作用主要是根据元素所对应的分数来获取集合中的元素,即返回分数大于等于
min
并且小于等于
max
的元素,命令中的可选参数
withscorea
则是表示是否需要返回元素所对应的分数,后面还有一个可选参数
limit
,则类似于
MySQL
数据中进行分页的关键字
limit
,同样的,这里的
offset
也是表示从第多少个元素开始返回,而
count
则是表示每次返回多少个元素,具体使用可以如下:
zrangebyscore zset 2 4
上面命令则是表示返回
zset
集合中分数在
2
和
4
之间的元素。
zrevrangebyscore key max min [withscores] [limit offset count]
zrevrangebyscore
命令同样也是根据分数来获取集合中的元素,不过和
zrangebyscore
命令不同的是,
zrevrangebyscore
命令是根据分数从高到低来进行排列元素的,需要注意的一点是,在使用
zrevrangebyscore
命令的时候,参数中的分数的最大值是放在前面的,而分数的最小值是放在后面的,具体使用可以如下:
zrevrangebyscore zset 4 2
上面的命令则是获取分数在
2
和
4
之间的元素,并按分数从高到低进行排列返回。
zrank key member
zrank
命令是用来获取指定元素在集合中的索引值,当然,索引值是从
0
开始计数的,具体使用可以如下:
zrank zset d
上面这个命令便是获取
d
这个元素在
zset
集合中所在的索引值是多少。
zrevrank key member
zrevrank
命令也是用来获取指定元素在集合中的索引值的,只不过和
zrank
命令相反的是,
zrevrank
返回的顺序和
zrank
命令返回的刚好是相反的。具体使用可以如下:
zrevrank zset d
上面这个命令也是获取
d
这个元素在
zset
集合之中的索引值的,其实就是相当于,
zrank
命令获取索引值的时候是从前往后数的,而
zrevrank
命令是从后往前数的。
zscore key member
zscore
命令的作用就是获取集合中指定元素所对应的分数,当元素不存在时就直接返回
nil
了,具体使用可以如下:
zscore zset d
上面这个命令就是获取
d
这个元素在
zset
集合中所对应的分数。
zrem key member [member...]
zrem
命令是用来删除集合中指定元素的,如果命令中的元素在集合中并不存在时,则直接忽略,具体使用可以如下:
zrem zset a
上面这个命令就是直接删除掉
zset
集合中的
a
元素。
zremrangebyrank key start stop
zremrangebyrank
命令则是根据元素的索引值来删除集合中的元素,
start
和
stop
都是表示的索引值,从
0
开始计数,
0
表示的是第一个元素,而
-1
则是表示的最后一个元素,命令的作用就是删除索引值在
start
和
stop
之间的元素,具体使用可以如下:
zremrangebyrank zset 0 0
上面这个命令便是相当于删除
zset
集合中索引值为
0
的元素。
zremrangebyscore key min max
zrenrangebyscore
命令则是根据元素所对应的分数来删除元素,将分数处在
min
和
max
之间的元素进行删除,具体使用可以如下:
zremrangebyscore zset 5 5
上面命令则是删除
zset
集合中元素对应分数为
5
的元素。
keys pattern
keys
命令的作用是列出所有匹配给定模式的
key
,其中的
pattern
参数即为正则表达式,在实际生产中,还是应该尽量避免使用该命令的,因为该命令是非常耗时的,对
Redis
数据库的性能消耗也是非常高的,下面我们来看一下具体使用:
keys *
上面这个命令的作用便是列出当前数据库中的所有
key
,因为生产环境的数据量都是很大的,因此在生产环境最好不要使用该命令。
del key [key...]
del
命令则是用于删除
Redis
数据库中指定的
key
,当然当命令参数中的
key
不存在时,那就会直接将
key
忽略掉了,下面看具体使用:
del name
上面的命令则是直接删除掉
name
这个
key
。
exists key
exists
命令主要是用来判断指定
key
在当前数据库中是否存在,如果存在则是返回
1
,不存在则是返回
0
,下面看具体使用:
exists name
上面这个命令便是判断
name
这个
key
是否存在于当前的数据库中。
move key db
move
命令的作用就是将指定的
key
移动到指定的数据库中,当指定的
key
在目标数据库中已经存在或者在当前数据库中不存在时,移动操作就不会发生。在
Redis
的配置文件
redis.conf
中默认配置的数据库数量是
16
,而我们默认使用的数据库是
0
号数据库,当我们想切换数据库时就可以使用
select
命令,比如想切换到
10
号数据库,那我们就可以使用
select 10
这个命令,下面我们来看移动指定的
key
到别的数据库的命令。
move name 10
上面这个命令便是将
name
这个
key
移动到了
10
号数据库。
rename key newkey
rename
命令主要是为指定的
key
改名,如果当
newkey
已经存在时,那么命令实际的效果就是
key
所对应的数据会覆盖
newkey
所对应的数据,下面看具体使用:
rename username name
上面的命令就是将
username
这个
key
名称替换为
name
,当
name
这个
key
在之前就已经存在时,那么就会使用
username
这个
key
所对应的数据去覆盖
name
这个
key
所对应的数据。
renamenx key newkey
renamenx
这个命令同样也是为指定的
key
改名,但是稍有不用的是,只有当
newkey
不存在时,操作才会执行成功,当返回值为
1
时表示操作成功,为
0
时则表示操作失败,下面看具体使用:
renamenx username name
上面这个命令便是将
username
这个
key
名称修改为
name
,当然只有当
name
这个名称不存在时才会成功。
expire key second
expire
命令是用来设置指定
key
的有效时间的,这里的有效时间主要是秒数了,在我们之前的操作中,都是没有设置有效期的,那默认的就是永久有效,但是在实际生产中,所有的数据都是永久有效的话,就会占用相当大空间的内存,同时有些数据保留永久也没有很大意义,这样的话,为了优化,我们一般会对数据设置一个有效时间,这样就能保证缓存空间的大小不会过大,下面我们来看该命令的具体使用:
expire name 100
上面这个命令便是设置
name
这个
key
的有效时间为
100
秒,当时间过了
100
秒之后,该
key
就会自动被删除了,同时对应的数据也就被删除了。
expireat key timestamp
expireat
命令同样也是用来设置有效时间的,不过不同之处在于,
expireat
是使用的绝对时间,而不是相对时间,该时间参数是
Unix timestamp
格式的,也就是从
1970-01-01
这一天开始所流经的秒数,因此可以想到使用该命令设置有效时间时是一个很大的数了,具体使用可以如下:
expireat name 100
上面这个命令的作用是设置
name
这个
key
有效时间为
1970-01-01
开始时的
100
秒,当我们再次查看该
key
时,就会发现这个
key
已经过期了,这是因为我们现在肯定远远过去
1970-01-01
这一天很长时间了。
ttl key
ttl
命令用于获取指定
key
剩下的有效生存时间,当默认情况下,
key
是永久生效时,使用
ttl
命令会返回
-1
,表示是永久有效的,当然对于这个
key
来说,之前指定的有效生存时间也就永久延长了,具体使用可以如下:
ttl name
上面这个命令便是查看
name
这个
key
所剩下的有效生存时间,因为本身时间也会自然流逝,因此每次我们使用该命令时,所返回的结果也是不一样的,不过肯定是慢慢减少的。
persist key
persist
命令的作用是在当
key
有生效时间时,将
key
所对应的生效时间设置为永久,并且可以持久化存储,当
key
的有效时间被设置为永久之后,我们再使用
ttl
命令查看
key
所对应的有效时间就会返回
-1
了,下面看具体使用:
persist name
上面这个命令便是将
name
这个
key
所对应的有效生存时间设置为永久。
randomkey
randomkey
命令的作用便是从当前数据库中随机返回一个
key
,当然具体的使用也就是直接调用该命令了。
type key
type
命令用于返回指定
key
所对应的数据类型,因为
Redis
只有
5
种数据类型,因此返回值也就只有这
5
种,具体为
string
,
list
,
set
,
hash
和
zset
,同时当命令中的
key
在数据库中并不存在时,那这时候就会返回
none
了。具体使用可以如下:
type name
上面这个命令便是返回
name
这个
key
所对应的数据类型了,很明显这时候返回的应该是
string
。
下面我们再来看
Redis
数据库中的事务,和
MySQL
数据库中一样,
Redis
数据库中的事务也有两个特点:
1.事务是一个单独的隔离操作。
2.事务是一个原子操作。
事务是一个单独的隔离操作,是表示事务中所有的命令都会序列化,按顺序进行执行,在事务执行命令的过程中,不会被其它客户端发送的命令请求所打断;事务是一个原子操作,表示在事务中的多个命令,要么全部执行成功,要么全部执行失败。
关于事务的命令有如下这些,我们先看一下:
multi:表示事务开始
exec:表示执行事务
discard:表示取消事务
watch:表示对指定key进行监视
unwatch:取消对指定key的监视
下面我们通过事务执行的流程,来对事务相关的命令进行详细说明,事务执行的一般流程为先开启事务,然后多个命令进入事务队列,最后我们就是执行事务或者取消事务,这边是一个完整的事务流程,针对上面说的流程,我们的一般命令的执行流程为:
执行事务:
multi
多条命令入队
取消事务:
multi
多条命令入队
discard
需要说明的是,当我们取消事务时,事务中对
key
执行的操作都不会生效,下面我们再看最后的两个命令,
watch
和
unwatch
命令。
watch
命令的作用是监视一个或多个
key
,在事务执行之前如果有别的命令对
key
有修改操作的话,那事务将会被打断;
unwatch
命令则是用于取消
watch
命令对于
key
的监视。
首先我们需要得到
Jedis
的
jar
包,我们这里使用的是
jedis-2.8.2.jar
,有了
jar
包我们就能使用其中提供的工具类完成我们想要的功能了,所以我们就将上面这个
jar
包加入到我们的工程当中,下面我们就开始写代码连接
Redis
数据库了。
Jedis jedis = new Jedis("10.21.10.27", 6379);
jedis.set("name", "kobe");
String name = jedis.get("name");
System.out.println(name);
上面的代码便是连接
Redis
,然后往里面存入一个
key
为
name
的键值对,我们下面再获取其对应的值,预想是可以得到我们想要的值的,执行代码,我们会发现有报错,报错为
connect timed out
,也就是说未连接到
Redis
数据库,那这是什么原因呢?其实我们在之前就已经提到过,
Redis
出于安全考虑,默认情况下只允许本地访问,因此当我们在
windows
中写代码访问
Linux
中安装的
Redis
数据库时是访问不了的,因此我们应该允许
Redis
数据库被外围访问,这个设置是在
Redis
的配置文件
redis.conf
当中进行设置的,也就是:
bind 127.0.0.1
我们需要做的修改就是使用
#
将这句设置注释掉,注释掉之后,
Redis
数据库就能被外围所访问了,因此当我们修改好配置文件之后,就可以重启
Redis
数据库了,然后我们就可以接着执行上面的代码,看看是否可以了,执行的话发现还是不行,这次的报错信息是没有设置密码,因此我们需要设置
Redis
数据库的密码,同样也是在配置文件
redis.conf
当中,就是:
# requirepass foobared
默认情况下是被注释的,也就是没有密码的,然后我们就需要将上面注释放开,然后设置新的密码,比如下面这样:
requirepass admin
这样就是设置
Redis
数据库的密码为
admin
了,当然修改了
Redis
的密码设置之后,同样也是需要重启
Redis
数据库的,这时候我们的代码也需要做一些调整,也就是使用密码去做认证,具体的代码如下:
Jedis jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
jedis.set("name", "kobe");
String name = jedis.get("name");
System.out.println(name);
这样再执行代码的话我们就可以得到预期的结果了,还有一点需要说明的是,当我们
Redis
的服务端设置了密码之后,我们再使用
Redis
命令行客户端进行连接时,可以使用如下的命令:
./redis-cli -h 127.0.0.1 -p 6379 -a admin
在上面的命令中,我们指定密码时使用的
-a
参数,这样的话当服务器端设置了密码我们也能在客户端进行连接了。
由于之前已经介绍了
Redis
中所提供命令的作用,而且
Jedis
提供方法的名称也是和命令一致的,那我们就直接看代码了。
public class RedisDemo2 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
// set和get
@Test
public void test() {
jedis.set("name", "kobe");
String name = jedis.get("name");
System.out.println(name);
// mset和mget
@Test
public void test2() {
jedis.mset("password", "admin", "age", "20");
List<String> values = jedis.mget("name", "password", "age");
System.out.println(values);
// append setrange getrange
@Test
public void test3() {
// jedis.append("name", " is boy");
System.out.println(jedis.get("name"));
jedis.setrange("name", 8, "girl");
System.out.println(jedis.get("name"));
System.out.println(jedis.getrange("name", 8, -1));
看上面代码中的每一个测试方法应该都是非常好理解的,因为每个方法的作用都是和命令是一致的,这里只是简单地演示了几个方法,不过其它的方法也是类似的,因此大家可以自己探索。
public class RedisDemo3 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
@After
public void destroyJedis() throws IOException {
if (null != jedis) {
jedis.close();
// lpush lrange
@Test
public void test() {
jedis.lpush("names", "tom", "jerry", "kobe", "james");
List<String> names = jedis.lrange("names", 0, -1);
System.out.println(names);
// lset
@Test
public void test2() {
jedis.lset("names", 0, "wade");
List<String> names = jedis.lrange("names", 0, -1);
System.out.println(names);
// lindex
@Test
public void test3() {
String value = jedis.lindex("names", 1);
System.out.println(value);
// linsert
@Test
public void test4() {
jedis.linsert("names", LIST_POSITION.BEFORE, "kobe", "james");
List<String> names = jedis.lrange("names", 0, -1);
System.out.println(names);
// lrem
@Test
public void test5() {
jedis.lrem("names", 1, "james");
List<String> names = jedis.lrange("names", 0, -1);
System.out.println(names);
下面我们开始介绍使用
Jedis
操作
Redis
数据库中的
hash
类型数据,同样的我们也是直接给出代码了。
public class RedisDemo4 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
@After
public void destroyJedis() throws IOException {
if (null != jedis) {
jedis.close();
// hset hget
@Test
public void test() {
jedis.hset("user", "username", "tom");
String username = jedis.hget("user", "username");
System.out.println(username);
// hmset hmget
@Test
public void test2() {
Map<String, String> map = new HashMap<>();
map.put("password", "123");
map.put("sex", "male");
jedis.hmset("user", map);
List<String> values = jedis.hmget("user", "username", "password", "sex");
System.out.println(values);
// hgetall hkeys kvals
@Test
public void test3() {
Map<String, String> map = jedis.hgetAll("user");
for (String key : map.keySet()) {
System.out.println(key + " " + map.get(key));
Set<String> keys = jedis.hkeys("user");
System.out.println(keys);
List<String> vals = jedis.hvals("user");
System.out.println(vals);
// hdel
@Test
public void test4() {
jedis.hdel("user", "sex");
Map<String, String> map = jedis.hgetAll("user");
for (String key : map.keySet()) {
System.out.println(key + " " + map.get(key));
下面我们再来介绍使用
Jedis
操作
Redis
数据库中的
set
类型数据,同样的我们直接看代码:
public class RedisDemo5 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
@After
public void destroyJedis() throws IOException {
if (null != jedis) {
jedis.close();
// sadd smembers
@Test
public void test() {
jedis.sadd("language", "java", "c++", "ruby", "python");
Set<String> smembers = jedis.smembers("language");
System.out.println(smembers);
// srem
@Test
public void test2() {
jedis.srem("language", "java");
Set<String> smembers = jedis.smembers("language");
System.out.println(smembers);
// sdiff
@Test
public void test3() {
jedis.sadd("language", "java", "c++", "ruby", "python");
jedis.sadd("language2", "c", "c++", "c#", "php");
Set<String> sdiff = jedis.sdiff("language", "language2");
System.out.println(sdiff);
// sinter
@Test
public void test4() {
jedis.sadd("language", "java", "c++", "ruby", "python");
jedis.sadd("language2", "c", "c++", "c#", "php");
Set<String> sinter = jedis.sinter("language", "language2");
System.out.println(sinter);
// sunion
@Test
public void test5() {
jedis.sadd("language", "java", "c++", "ruby", "python");
jedis.sadd("language2", "c", "c++", "c#", "php");
Set<String> sunion = jedis.sunion("language", "language2");
System.out.println(sunion);
下面我们开始介绍使用
Jedis
操作
Redis
数据库中的
sortedSet
类型数据,同样的我们直接看代码:
public class RedisDemo6 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
@After
public void destroyJedis() throws IOException {
if (null != jedis) {
jedis.close();
// zadd zrange zrangeByScore
@Test
public void test() {
Map<String, Double> map = new HashMap<>();
map.put("张三", 60.0);
map.put("李四", 70.0);
map.put("王五", 80.0);
map.put("赵六", 90.0);
map.put("孙七", 50.0);
jedis.zadd("zset", map);
Set<String> zset = jedis.zrange("zset", 0, -1);
System.out.println(zset);
Set<String> zset2 = jedis.zrangeByScore("zset", 70, 90);
System.out.println(zset2);
// zrangeWithScores
@Test
public void test2() {
Map<String, Double> map = new HashMap<>();
map.put("张三", 60.0);
map.put("李四", 70.0);
map.put("王五", 80.0);
map.put("赵六", 90.0);
map.put("孙七", 50.0);
jedis.zadd("zset", map);
Set<Tuple> tuples = jedis.zrangeWithScores("zset", 0, -1);
for (Tuple tuple : tuples) {
System.out.println(tuple.getScore() + " " + tuple.getElement());
// zrank
@Test
public void test3() {
Map<String, Double> map = new HashMap<>();
map.put("张三", 60.0);
map.put("李四", 70.0);
map.put("王五", 80.0);
map.put("赵六", 90.0);
map.put("孙七", 50.0);
jedis.zadd("zset", map);
Long zrank = jedis.zrank("zset", "李四");
System.out.println(zrank);
// zscore
@Test
public void test4() {
Map<String, Double> map = new HashMap<>();
map.put("张三", 60.0);
map.put("李四", 70.0);
map.put("王五", 80.0);
map.put("赵六", 90.0);
map.put("孙七", 50.0);
jedis.zadd("zset", map);
Double zscore = jedis.zscore("zset", "张三");
System.out.println(zscore);
// zrem
@Test
public void test5() {
Map<String, Double> map = new HashMap<>();
map.put("张三", 60.0);
map.put("李四", 70.0);
map.put("王五", 80.0);
map.put("赵六", 90.0);
map.put("孙七", 50.0);
jedis.zadd("zset", map);
jedis.zrem("zset", "王五");
Set<Tuple> tuples = jedis.zrangeWithScores("zset", 0, -1);
for (Tuple tuple : tuples) {
System.out.println(tuple.getScore() + " " + tuple.getElement());
下面我们开始介绍使用
Jedis
进行
Redis
中
key
的通用操作,比如获取
Redis
数据库中所有的
key
,删除某些
key
,对
key
设置过期时间之类的,我们先看具体的代码:
public class RedisDemo7 {
private Jedis jedis;
@Before
public void createJedis() {
jedis = new Jedis("10.21.10.27", 6379);
jedis.auth("admin");
@After
public void destroyJedis() throws IOException {
if (null != jedis) {
jedis.close();
// keys pattern
@Test
public void test() {
Set<String> keys = jedis.keys("*");
System.out.println(keys);
// del
@Test
public void test2() {
Long del = jedis.del("user");
System.out.println(del);
// 关于key的时间设置
@Test
public void test3() throws ParseException {
jedis.set("name", "kobe");
String name = jedis.get("name");
System.out.println(name);
Long ttl = jedis.ttl("name");
System.out.println(ttl);
jedis.expire("name", 100);
Long ttl2 = jedis.ttl("name");
System.out.println(ttl2);
jedis.persist("name");
Long ttl3 = jedis.ttl("name");
System.out.println(ttl3);
关于对
key
设置过期时间,在默认情况下,
key
在
Redis
数据库中是永久有效的,我们使用
ttl()
方法查看
key
的有效期时,返回值为
-1
,当我们使用
expire()
方法为
key
设置了有效期之后,然后再使用
ttl()
方法获取有效期时,那返回的就是剩余的有效期了,最后
persist()
方法是将
key
的有效期限设置为永远,也就是使
key
在
Redis
数据库中永久有效。
下面我们来介绍一下
Redis
的数据持久化方面知识,
Redis
数据库的数据持久化方式一共有
2
种,那就是
RDB
和
AOF
持久化方式,我们先分别介绍一下:
RDB持久化:在指定的时间间隔内将内存中的数据集快照写入到磁盘上面。
AOF持久化:以日志的形式记录服务器端进行的每一个写操作,在Redis数据库启动之时,会读取该文件构建数据库,保证启动之后数据库中的数据是完整的。
了解了
Redis
数据库的两种持久化方式之后,我们可以在
Redis
数据库中使用的持久化机制就有下面
4
种了。
1.RDB持久化;
2.AOF持久化;
3.同时应用RDB和AOF;
4.无持久化。
介绍了
Redis
数据库持久化机制之后,下面再对
RDB
和
AOF
这两种持久化方式进行详细说明。
save 900 1
save 300 10
save 60 10000
这便是针对于
RDB
持久化方式进行的设置,前面一个数字为时间的秒数,后一个数字为操作
key
的个数,比如
save 900 1
,就是表示如果在
900
秒以内有
1
个
key
被修改的话,那么就会将内存中的数据集快照写入到硬盘中的
dump.rdb
文件,当然这个
dump.rdb
文件名称也是在
redis.conf
配置文件中进行配置的,这样的话,其它的配置也是一样的了,都是在多少秒之内有多少个
key
被修改就会将内存快照写入到磁盘当中。
如果想要启用
AOF
方式的持久化的话,那就需要修改
redis.conf
文件当中的一个配置,也就是:
appendonly no
修改的方式也就是将其中的
no
改为
yes
,这样的话便是启用
AOF
的持久化方式了。
AOF
持久化方式的策略一共有三种,在
redis.conf
配置文件中的默认配置为:
# appendfsync always
appendfsync everysec
# appendfsync no
可以看出一共是三种方式,第一种为每次有修改操作时都会追加写
AOF
文件;第二种为每一秒进行追加写
AOF
文件;第三种则是不同步。从上面的设置可以看出默认是采用的第二种方式,也就是每秒钟进行追加写
AOF
文件,这种方式通常情况也是最适中的。
关于
AOF
持久化方式,还有一点需要说明的是,因为是采用的追加写日志的方式,因此我们是可以对日志文件进行瘦身处理的,也就是只保留对
key
修改最近的一条,这样的话也是能保证数据是完整的,其实在
redis.conf
文件中也有配置,那就是:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
第一条设置是说当对操作记录追加写的比率达到
100%
时,就会进行自动瘦身了;第二条则是当日志文件大小达到
64mb
时,也会进行自动瘦身操作。其实除了配置之外,我们还可以使用命令来主动进行文件瘦身,那就是
bgrewriteaof
命令了。
上面已经介绍了
RDB
和
AOF
方式的相关特性,下面我们就将它们对比来看一下彼此的优缺点。
RDB方式:
1.数据的备份和恢复非常方便,因为一个数据库只有一个持久化文件;
2.性能更高;对Redis服务进程来说,当需要做持久化时,只需要创建出子进程,然后让子进程去做这些持久化的工作,这样就可以避免服务进程进行IO操作了;
3.对比AOF来说,当持久化文件较大时,RDB方式的启动效率会更高。
1.当系统在持久化时宕机,那还没来得及写入磁盘的数据就会丢失了;
2.由于RDB方式是通过创建子进程来协助完成数据持久化工作的,当要持久化的数据集较大时,可能会导致整个服务器停止服务几百毫秒;
AOF方式:
1.更高的数据安全性,也就是数据持久性,提供了3种同步策略,每秒同步,每次修改同步和不同步;
2.由于对持久化文件是采用追加写入的方式,因此即使在写入过程中发生服务器宕机,也不会影响已经写入的数据内容;
3.当持久化文件过大时,Redis可以进行自动瘦身;
4.AOF日志文件格式清晰,便于理解,很容易用该文件完成数据的重建。
1.对于相同的数据来说,AOF文件要大于RDB持久化文件;
2.根据同步策略的不同,AOF运行的效率会慢于RDB方式。每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB是一样的。
气势凌人的茶叶 · 杭州市热门民办小学学费统计 1 月前 |