NoSQL,泛指非关系型的数据库,它可以作为关系型数据库的良好补充。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
NoSQL数据库的四大分类如下:
1). 键值(Key-Value)存储数据库
2). 列存储数据库
3). 文档型数据库
4). 图形(Graph)数据库
redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如下:
redis是C语言开发,建议在linux上运行,在这使用Centos7作为安装环境。
安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc:yum install gcc-c++(root用户)
下载redis,在这使用redis-4.0.14版本
wget http://download.redis.io/releases/redis-4.0.14.tar.gz
#将redis-4.0.14.tar.gz拷贝到/usr/local下
解压源码
tar -zxvf redis-4.0.14.tar.gz
进入解压后的目录进行编译
cd /usr/local/redis-4.0.14
make
安装到指定目录,如 /usr/local/redis
cd /usr/local/redis-4.0.14
make PREFIX=/usr/local/redis install
redis.conf是redis的配置文件,redis.conf在redis源码目录。
注意修改port作为redis进程的端口,port默认6379。
拷贝配置文件到安装目录下。将源码目录中的配置文件 redis.conf 其拷贝到安装路径下。并设置redis可远程访问,修改绑定地址为 0.0.0.0
cp /usr/local/redis-4.0.14/redis.conf /usr/local/redis/bin
# 编辑redis.conf文件,并修改绑定地址为 0.0.0.0
vi redis.conf
bind 0.0.0.0
到这单机的redis就搭建好了,当然在微服务架构中要搭建集群来保证高可用。
在安装目录下bin/redis-server用来启动redis服务端,输入 /usr/local/redis/bin/redis-server 即可启动。
强行终止Redis进程可能会导致redis持久化数据丢失。正确停止Redis的方式应该是向Redis服务发送SHUTDOWN命令,方法为:
cd /usr/local/redis
./bin/redis-cli shutdown save
连接本机6379端口的redis服务执行shutdown停止
save:在停止redis服务之前将所有的数据持久化保存。
停止其他端口的redis
cd /usr/local/redis
./bin/redis-cli -p 6380 shutdown save
执行bin/redis-cli连接本地redis服务端: ./redis-cli
指定连接redis服务的ip和端口: ./redis-cli -h 192.168.10.131 -p 6380
redis提供了ping命令来测试客户端与redis的连接是否正常,如果连接正常会收到回复PONG
一个redis进程就是一个redis实例,一台服务器可以同时有多个redis实例,不同的redis实例提供不同的服务端口对外提供服务,每个redis实例之间互相影响。每个redis实例都包括自己的数据库,数据库中可以存储自己的数据。
一个Redis实例可以包括多个数据库,客户端可以指定连接某个redis实例的哪个数据库,就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库。
一个redis实例最多可提供16个数据库,下标从0到15,客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库,如下连接1号库,在1号库中查询上节设置的数据,结果查询不到:
重新选择第0号数据库,查询数据:
如果选择一个不存在数据库则会报错:
注意:redis不支持修改数据库的名称,只能通过select 0、select 1…选择数据库。
redis数据就是以key-value形式来存储的,key只能是字符串类型,value可以是以下五种类型:String、List、Set、SortedSets、Hash。
命令不区分大小写,但key和value区分大小写。命令不需要记住,要用的时候再来查找就可以了
127.0.0.1:6379> select 0 #切换到第1个数据库,默认共有16个数据库,索引从0开始
OK
127.0.0.1:6379> keys * #显示所有的键key
(empty list or set)
127.0.0.1:6379> set name tom #设置键
OK
127.0.0.1:6379> get name #获取键对应的值
"tom"
127.0.0.1:6379> exists mykey #判断该键是否存在,存在返回1,不存在返回
(integer) 0
127.0.0.1:6379> append mykey "hello" #如果该键不存在,则创建,返回当前value的长度
(integer) 5
127.0.0.1:6379> append mykey " world" #如果该键已经存在,则追加,返回追加后value的长度
(integer) 11
127.0.0.1:6379> get mykey #获取mykey的值
"hello world"
127.0.0.1:6379> strlen mykey #获取mykey的长度
(integer) 11
#EX和PX表示失效时间,单位为秒和毫秒,两者不能同时使用;NX表示数据库中不存在时才能设置,XX表示存在时才能设置
127.0.0.1:6379> set mykey "this is test" EX 5 NX
OK
127.0.0.1:6379> get mykey
"this is test"
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> set mykey 20
OK
127.0.0.1:6379> incr mykey #递增1
(integer) 21
127.0.0.1:6379> decr mykey #递减1
(integer) 20
127.0.0.1:6379> del mykey #删除该键
(integer) 1
127.0.0.1:6379> decr mykey
(integer) 1
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> INCR mykey
(integer) 1
127.0.0.1:6379> set mykey 'hello' #将该键的Value设置为不能转换为整型的普通字符串
OK
127.0.0.1:6379> incr mykey #在该键上再次执行递增操作时,Redis将报告错误信息
(error) ERR value is not an integer or out of range
127.0.0.1:6379> set mykey 10
OK
127.0.0.1:6379> incrby mykey 5 #递增5,即步长
(integer) 15
127.0.0.1:6379> decrby mykey 10 #递减10
(integer) 5
# getset 获取的同时并设置新的值
127.0.0.1:6379> incr mycount #将计数器的值原子性的递增1
(integer) 1
127.0.0.1:6379> getset mycount 666 #在获取计数器原有值的同时,并将其设置为新值
"1"
127.0.0.1:6379> get mycount
"666"
# setex 设置过期时间
127.0.0.1:6379> setex mykey 10 "hello" #设置指定Key的过期时间为10秒,等同于set mykey hello ex 10
OK
127.0.0.1:6379> ttl mykey #查看指定Key的过期时间(秒数)
(integer) 8
# setnx 当key不存在时才能设置
127.0.0.1:6379> del mykey
(integer) 0
127.0.0.1:6379> setnx mykey "aaa" #key不存在,可以设置,等同于set mykey aaa nx
(integer) 1
127.0.0.1:6379> setnx mykey "bbb" #key存在,不能设置
(integer) 0
127.0.0.1:6379> get mykey
"aaa"
127.0.0.1:6379> set mykey "hello world"
OK
127.0.0.1:6379> get mykey
"hello world"
127.0.0.1:6379> setrange mykey 6 dd #从索引为6的位置开始替换(索引从0开始)
(integer) 11
127.0.0.1:6379> get mykey
"hello ddrld"
127.0.0.1:6379> setrange mykey 20 dd #超过的长度使用0代替
(integer) 22
127.0.0.1:6379> get mykey
"hello ddrld\x00\x00\x00\x00\x00\x00\x00\x00\x00dd"
127.0.0.1:6379> getrange mykey 3 12 #获取索引为[3,12]之间的内容
"lo ddrld\x00\x00"
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> setbit mykey 7 1 #设置从0开始计算的第七位BIT值为1,返回原有BIT值0
(integer) 0
127.0.0.1:6379> get mykey #获取设置的结果,二进制的0000 0001的十六进制值为0x01
"\x01"
127.0.0.1:6379> setbit mykey 6 1 #设置从0开始计算的第六位BIT值为1,返回原有BIT值0
(integer) 0
127.0.0.1:6379> get mykey #获取设置的结果,二进制的0000 0011的十六进制值为0x03
"\x03"
127.0.0.1:6379> getbit mykey 6 #返回了指定Offset的BIT值
(integer) 1
127.0.0.1:6379> getbit mykey 10 #如果offset已经超出了value的长度,则返回0
(integer) 0
127.0.0.1:6379> mset key1 "hello" key2 "world" #批量设置了key1和key2两个键
OK
127.0.0.1:6379> mget key1 key2 #批量获取了key1和key2两个键的值。
1) "hello"
2) "world"
#批量设置了key3和key4两个键,因为之前他们并不存在,所以该命令执行成功并返回1
127.0.0.1:6379> msetnx key3 "itany" key4 "liu"
(integer) 1
127.0.0.1:6379> mget key3 key4
1) "itany"
2) "liu"
#批量设置了key3和key5两个键,但是key3已经存在,所以该命令执行失败并返回0
127.0.0.1:6379> msetnx key3 "hello" key5 "world"
(integer) 0
#批量获取key3和key5,由于key5没有设置成功,所以返回nil
127.0.0.1:6379> mget key3 key5
1) "itany"
2) (nil)
127.0.0.1:6379> flushdb
OK
#创建键mykey及与其关联的List,然后将参数中的values从左到右依次插入
127.0.0.1:6379> lpush mykey a b c d
(integer) 4
127.0.0.1:6379> lrange mykey 0 2 #获取从位置0开始到位置2结束的3个元素
1) "d"
2) "c"
3) "b"
#获取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素
127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> lrange mykey -3 -2 #获取从倒数第3个到倒数第2个的元素
1) "c"
2) "b"
#lpushx表示键存在时才能插入,mykey2键此时并不存在,因此该命令将不会进行任何操作,其返回值为0
127.0.0.1:6379> lpushx mykey2 e
(integer) 0
#可以看到mykey2没有关联任何List Value
127.0.0.1:6379> lrange mykey2 0 -1
(empty list or set)
#mykey键此时已经存在,所以该命令插入成功,并返回链表中当前元素的数量
127.0.0.1:6379> lpushx mykey e
(integer) 5
#获取该键的List中的第一个元素
127.0.0.1:6379> lrange mykey 0 0
1) "e"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush mykey a b c d
(integer) 4
#取出链表头部的元素,该元素在链表中就已经不存在了
127.0.0.1:6379> lpop mykey
"d"
127.0.0.1:6379> lpop mykey
"c"
#在执行lpop命令两次后,链表头部的两个元素已经被弹出,此时链表中元素的数量是2
127.0.0.1:6379> llen mykey
(integer) 2
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush mykey a b c d a c
(integer) 6
#从头部(left)向尾部(right)操作链表,删除2个值等于a的元素,返回值为实际删除的数量
127.0.0.1:6379> lrem mykey 2 a
(integer) 2
127.0.0.1:6379> lrange mykey 0 -1 #查看删除后链表中的全部元素
1) "c"
2) "d"
3) "c"
4) "b"
127.0.0.1:6379> lindex mykey 1 #获取索引值为1(头部的第二个元素)的元素值
"d"
127.0.0.1:6379> lset mykey 1 e #将索引值为1(头部的第二个元素)的元素值设置为新值e
OK
127.0.0.1:6379> lindex mykey 1 #查看是否设置成功
"e"
127.0.0.1:6379> lindex mykey 6 #索引值6超过了链表中元素的数量,该命令返回nil
(nil)
#设置的索引值6超过了链表中元素的数量,设置失败,该命令返回错误信息。
127.0.0.1:6379> lset mykey 6 h
(error) ERR index out of range
#仅保留索引值0到2之间的3个元素,注意第0个和第2个元素均被保留。
127.0.0.1:6379> ltrim mykey 0 2
OK
127.0.0.1:6379> lrange mykey 0 -1 #查看trim后的结果
1) "c"
2) "e"
3) "c"
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> lpush mykey a b c d e
(integer) 5
127.0.0.1:6379> linsert mykey before a a1 #在a的前面插入新元素a1
(integer) 6
127.0.0.1:6379> lrange mykey 0 -1 #查看是否插入成功,从结果看已经插入
1) "e"
2) "d"
3) "c"
4) "b"
5) "a1"
6) "a"
127.0.0.1:6379> linsert mykey after e e2 #在e的后面插入新元素e2,从返回结果看已经插入成功
(integer) 7
127.0.0.1:6379> lrange mykey 0 -1 #再次查看是否插入成功
1) "e"
2) "e2"
3) "d"
4) "c"
5) "b"
6) "a1"
7) "a"
127.0.0.1:6379> linsert mykey after k a #在不存在的元素之前或之后插入新元素,该命令操作失败,并返回1
(integer) 1
127.0.0.1:6379> linsert mykey1 after a a2 #在不存在的Key插入新元素,该命令操作失败,返回0
(integer) 0
127.0.0.1:6379> del mykey
(integer) 1
#从链表的尾部插入参数中给出的values,插入顺序是从左到右依次插入
127.0.0.1:6379> rpush mykey a b c d
(integer) 4
127.0.0.1:6379> lrange mykey 0 -1 #查看链表中的元素,注意元素的顺序
1) "a"
2) "b"
3) "c"
4) "d"
#该键已经存在并且包含4个元素,rpushx命令将执行成功,并将元素e插入到链表的尾部。
127.0.0.1:6379> rpushx mykey e
(integer) 5
#由于mykey2键并不存在,因此该命令不会插入数据,其返回值为0。
127.0.0.1:6379> rpushx mykey2 e
(integer) 0
127.0.0.1:6379> lrange mykey 0 -1 #查看链表中所有的元素
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
127.0.0.1:6379> rpop mykey #从尾部(right)弹出元素,即取出元素
"e"
127.0.0.1:6379> lrange mykey 0 -1 #查看链表中所有的元素
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> lpush mykey2 m n #创建mykey2
(integer) 2
#将mykey的尾部元素弹出,然后插入到mykey2的头部(原子性的完成这两步操作)
127.0.0.1:6379> rpoplpush mykey mykey2
"d"
#通过lrange命令查看mykey在弹出尾部元素后的结果
127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
#通过lrange命令查看mykey2在插入元素后的结果
127.0.0.1:6379> lrange mykey2 0 -1
1) "d"
2) "n"
3) "m"
#将source和destination设为同一键,将mykey中的尾部元素移到其头部
127.0.0.1:6379> rpoplpush mykey mykey
"c"
127.0.0.1:6379> lrange mykey 0 -1 #查看结果
1) "c"
2) "a"
3) "b"
#由于该键myset之前并不存在,因此参数中的三个成员都被正常插入
127.0.0.1:6379> sadd myset a b c
(integer) 3
#查看集合中的元素,从结果可以,输出的顺序和插入顺序无关(无序的)
127.0.0.1:6379> smembers myset
1) "a"
2) "c"
3) "b"
#由于参数中的a在myset中已经存在,因此本次操作仅仅插入了d和e两个新成员(不允许重复)
127.0.0.1:6379> sadd myset a d e
(integer) 2
127.0.0.1:6379> smembers myset #查看插入的结果
1) "a"
2) "c"
3) "d"
4) "b"
5) "e"
127.0.0.1:6379> sismember myset a #判断a是否已经存在,返回值为1表示存在
(integer) 1
127.0.0.1:6379> sismember myset f #判断f是否已经存在,返回值为0表示不存在
(integer) 0
127.0.0.1:6379> scard myset #获取集合中元素的数量
(integer) 5
127.0.0.1:6379> del myset
(integer) 1
127.0.0.1:6379> sadd myset a b c d
(integer) 4
127.0.0.1:6379> smembers myset #查看集合中的元素
1) "c"
2) "d"
3) "a"
4) "b"
127.0.0.1:6379> srandmember myset #随机返回一个成员,成员还在集合中
"c"
127.0.0.1:6379> spop myset #取出一个成员,成员会从集合中删除
"b"
127.0.0.1:6379> smembers myset #查看移出后Set的成员信息
1) "c"
2) "d"
3) "a"
#从Set中移出a、d和f三个成员,其中f并不存在,因此只有a和d两个成员被移出,返回为2
127.0.0.1:6379> srem myset a d f
(integer) 2
127.0.0.1:6379> smembers myset #查看移出后的输出结果
1) "c"
127.0.0.1:6379> del myset
(integer) 1
#为后面的smove命令准备数据
127.0.0.1:6379> sadd myset a b
(integer) 2
127.0.0.1:6379> sadd myset2 c d
(integer) 2
#将a从myset移到myset2,从结果可以看出移动成功
127.0.0.1:6379> smove myset myset2 a
(integer) 1
#再次将a从myset移到myset2,由于此时a已经不是myset的成员了,因此移动失败并返回0。
127.0.0.1:6379> smove myset myset2 a
(integer) 0
#分别查看myset和myset2的成员,确认移动是否真的成功。
127.0.0.1:6379> smembers myset
1) "b"
127.0.0.1:6379> smembers myset2
1) "c"
2) "d"
3) "a"
127.0.0.1:6379> flushdb
OK
#准备测试数据
127.0.0.1:6379> sadd myset a b c d
(integer) 4
127.0.0.1:6379> sadd myset2 c
(integer) 1
127.0.0.1:6379> sadd myset3 a c e
(integer) 3
#获取多个集合之间的不同成员,要注意匹配的规则
#先将myset和myset2进行比较,a、b和d三个成员是两者之间的差异成员,然后再用这个结果继续和myset3进行差异比较,b和d是myset3不存在的成员(差集)
127.0.0.1:6379> sdiff myset myset2 myset3
1) "d"
2) "b"
127.0.0.1:6379> sdiff myset3 myset2 myset
1) "e"
#将3个集合的差异成员存储到与diffkey关联的Set中,并返回插入的成员数量
127.0.0.1:6379> sdiffstore diffkey myset myset2 myset3
(integer) 2
#查看一下sdiffstore的操作结果
127.0.0.1:6379> smembers diffkey
1) "d"
2) "b"
#获取多个集合之间的交集,这三个Set的成员交集只有c
127.0.0.1:6379> sinter myset myset2 myset3
1) "c"
#将3个集合中的交集成员存储到与interkey关联的Set中,并返回交集成员的数量
127.0.0.1:6379> sinterstore interkey myset myset2 myset3
(integer) 1
#查看一下sinterstore的操作结果
127.0.0.1:6379> smembers interkey
1) "c"
#获取多个集合之间的并集
127.0.0.1:6379> sunion myset myset2 myset3
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"
#将3个集合中成员的并集存储到unionkey关联的set中,并返回并集成员的数量
127.0.0.1:6379> sunionstore unionkey myset myset2 myset3
(integer) 5
#查看一下sunionstore的操作结果
127.0.0.1:6379> smembers unionkey
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"
# 添加一个分数为1的成员
127.0.0.1:6379> zadd myzset 1 "one"
(integer) 1
# 添加两个分数分别是2和3的两个成员
127.0.0.1:6379> zadd myzset 2 "two" 3 "three"
(integer) 2
# 通过索引获取元素,0表示第一个成员,-1表示最后一个成员。WITHSCORES选项表示返回的结果中包含每个成员及其分数,否则只返回成员
127.0.0.1:6379> zrange myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zcard myzset # 获取myzset键中成员的数量
(integer) 3
127.0.0.1:6379> zrank myzset one # 获取成员one在集合中的索引,0表示第一个位置
(integer) 0
127.0.0.1:6379> zrank myzset four # 成员four并不存在,因此返回nil
(nil)
# 获取符合指定条件的成员数量,分数满足表达式 1 <= score <= 2的成员的数量
127.0.0.1:6379> zcount myzset 1 2
(integer) 2
127.0.0.1:6379> zrem myzset one two # 删除成员one和two,返回实际删除成员的数量
(integer) 2
127.0.0.1:6379> zcard myzset # 查看是否删除成功
(integer) 1
127.0.0.1:6379> zscore myzset three # 获取成员three的分数。返回值是字符串形式
"3"
127.0.0.1:6379> zscore myzset two # 由于成员two已经被删除,所以该命令返回nil
(nil)
127.0.0.1:6379> zincrby myzset 2 three # 将成员three的分数增加2,并返回该成员更新后的分数
"5"
127.0.0.1:6379> zincrby myzset 1 three # 将成员three的分数增加1,并返回该成员更新后的分数
"4"
127.0.0.1:6379> zrange myzset 0 1 withscores # 查看在更新了成员的分数后是否正确
1) "three"
2) "4"
127.0.0.1:6379> del myzset
(integer) 1
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
#通过分数获取元素,获取分数满足表达式1 <= score <= 2的成员
127.0.0.1:6379> zrangebyscore myzset 1 2
1) "one"
2) "two"
#-inf表示第一个成员,+inf表示最后一个成员,limit后面的参数用于限制返回成员的数量,
#2表示从位置索引(0based)等于2的成员开始,取后面3个成员,类似于MySQL中的limit
127.0.0.1:6379> zrangebyscore myzset -inf +inf withscores limit 2 3
1) "three"
2) "3"
3) "four"
4) "4"
#根据分数删除成员,删除分数满足表达式1 <= score <= 2的成员,并返回实际删除的数量
127.0.0.1:6379> zremrangebyscore myzset 1 2
(integer) 2
#看出一下上面的删除是否成功
127.0.0.1:6379> zrange myzset 0 -1
1) "three"
2) "four"
#根据索引删除成员,删除索引满足表达式0 <= rank <= 1的成员
127.0.0.1:6379> zremrangebyrank myzset 0 1
(integer) 2
#查看上一条命令是否删除成功
127.0.0.1:6379> zcard myzset
(integer) 0
127.0.0.1:6379> del myzset
(integer) 0
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
#按索引从高到低的方式获取成员
127.0.0.1:6379> zrevrange myzset 0 -1 WITHSCORES
1) "four"
2) "4"
3) "three"
4) "3"
5) "two"
6) "2"
7) "one"
8) "1"
#由于是从高到低的排序,所以位置等于0的是four,1是three,并以此类推
127.0.0.1:6379> zrevrange myzset 1 3
1) "three"
2) "two"
3) "one"
#按索引从高到低的方式根据分数获取成员,分数满足表达式3 >= score >= 0的成员
127.0.0.1:6379> zrevrangebyscore myzset 3 0
1) "three"
2) "two"
3) "one"
#limit选项的含义等同于zrangebyscore中的该选项,只是在计算位置时按照相反的顺序计算和获取
127.0.0.1:6379> zrevrangebyscore myzset 4 0 limit 1 2
1) "three"
2) "two"
#获取成员one在集合中的索引,由于是从高到低的排序,所以one的位置是3
127.0.0.1:6379> zrevrank myzset one
(integer) 3
#由于是从高到低的排序,所以four的位置是0
127.0.0.1:6379> zrevrank myzset four
(integer) 0
#给键值为myhash的键设置字段为field1,值为itany
127.0.0.1:6379> hset myhash field1 "itany"
(integer) 1
#获取键值为myhash,字段为field1的值
127.0.0.1:6379> hget myhash field1
"itany"
#myhash键中不存在field2字段,因此返回nil
127.0.0.1:6379> hget myhash field2
(nil)
#给myhash关联的Hashes值添加一个新的字段field2,其值为liu
127.0.0.1:6379> hset myhash field2 "liu"
(integer) 1
#获取myhash键的字段数量
127.0.0.1:6379> hlen myhash
(integer) 2
#判断myhash键中是否存在字段名为field1的字段,由于存在,返回值为1
127.0.0.1:6379> hexists myhash field1
(integer) 1
#删除myhash键中字段名为field1的字段,删除成功返回1
127.0.0.1:6379> hdel myhash field1
(integer) 1
#再次删除myhash键中字段名为field1的字段,由于上一条命令已经将其删除,因为没有删除,返回0
127.0.0.1:6379> hdel myhash field1
(integer) 0
#通过hsetnx命令给myhash添加新字段field1,其值为itany,因为该字段已经被删除,所以该命令添加成功并返回1
127.0.0.1:6379> hsetnx myhash field1 "itany"
(integer) 1
#由于myhash的field1字段已经通过上一条命令添加成功,因为本条命令不做任何操作后返回0
127.0.0.1:6379> hsetnx myhash field1 "itany"
(integer) 0
127.0.0.1:6379> del myhash
(integer) 1
#准备测试数据
127.0.0.1:6379> hset myhash field 5
(integer) 1
#给myhash的field字段的值加1,返回加后的结果
127.0.0.1:6379> hincrby myhash field 1
(integer) 6
#给myhash的field字段的值加1,返回加后的结果
127.0.0.1:6379> hincrby myhash field 1
(integer) 5
#给myhash的field字段的值加10,返回加后的结果
127.0.0.1:6379> hincrby myhash field 10
(integer) 5
127.0.0.1:6379> del myhash
(integer) 1
#为该键 myhash,一次性设置多个字段,分别是 field1 = "hello", field2 = "world"
127.0.0.1:6379> hmset myhash field1 "hello" field2 "world"
OK
#获取 myhash 键的多个字段,其中 field3 并不存在,因为在返回结果中与该字段对应的值为 nil
127.0.0.1:6379> hmget myhash field1 field2 field3
1) "hello"
2) "world"
3) (nil)
#返回myhash键的所有字段及其值,从结果中可以看出,他们是逐对列出的
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
#仅获取myhash键中所有字段的名字
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
#仅获取myhash键中所有字段的值
127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"
redis 键命令用于管理 redis 的键。
redis 键命令的基本语法如下:
redis 127.0.0.1:6379> COMMAND KEY_NAME
127.0.0.1:6379> flushdb
OK
#添加String类型的数据
127.0.0.1:6379> set mykey 2
OK
#添加List类型的数据
127.0.0.1:6379> lpush mylist a b c
(integer) 3
#添加Set类型的数据
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
#添加SortedSet类型的数据
127.0.0.1:6379> zadd myzset 1 "one" 2 "two"
(integer) 2
#添加Hash类型的数据
127.0.0.1:6379> hset myhash username "tom"
(integer) 1
#根据参数中的模式,获取当前数据库中符合该模式的所有key,从输出可以看出,该命令在执行时并不区分与Key关联的Value类型
127.0.0.1:6379> keys my*
1) "myset"
2) "mykey"
3) "myzset"
4) "myhash"
5) "mylist"
#删除了两个Keys
127.0.0.1:6379> del mykey mylist
(integer) 2
#查看刚刚删除的Key是否还存在,从返回结果看,mykey确实已经删除了
127.0.0.1:6379> exists mykey
(integer) 0
#查看一下没有删除的Key,以和上面的命令结果进行比较
127.0.0.1:6379> exists myset
(integer) 1
#将当前数据库中的myset键移入到ID为1的数据库中
127.0.0.1:6379> move myset 1
(integer) 1
#切换到ID为1的数据库
127.0.0.1:6379> select 1
OK
#查看当前数据库中的所有key
127.0.0.1:6379[1]> keys *
1) "myset"
#在重新打开ID为0的缺省数据库
127.0.0.1:6379[1]> select 0
OK
#清空数据库
127.0.0.1:6379> flushdb
OK
#准备新的测试数据
127.0.0.1:6379> set mykey "hello"
OK
#将mykey改名为mykey1
127.0.0.1:6379> rename mykey mykey1
OK
#由于mykey已经被重新命名,再次获取将返回nil
127.0.0.1:6379> get mykey
(nil)
#通过新的键名获取
127.0.0.1:6379> get mykey1
"hello"
#为renamenx准备测试key
127.0.0.1:6379> set oldkey "hello"
OK
127.0.0.1:6379> set newkey "world"
OK
#当新名称不存在时才会执行。由于newkey已经存在,因此该命令未能成功执行
127.0.0.1:6379> renamenx oldkey newkey
(integer) 0
#查看newkey的值,发现它并没有被renamenx覆盖
127.0.0.1:6379> get newkey
"world"
127.0.0.1:6379> flushdb
OK
#准备测试数据,将该键的超时设置为100秒
127.0.0.1:6379> set mykey "hello" ex 100
OK
#通过ttl命令查看还剩多少秒
127.0.0.1:6379> ttl mykey
(integer) 97
#立刻执行persist命令,该存在超时的键变成持久化的键,即将该Key的超时去掉
127.0.0.1:6379> persist mykey
(integer) 1
#ttl的返回值告诉我们,该键已经没有超时了
127.0.0.1:6379> ttl mykey
(integer) -1
#为后面的expire命令准备数据
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> set mykey "hello"
OK
#设置该键的超时被100秒
127.0.0.1:6379> expire mykey 100
(integer) 1
#用ttl命令看当前还剩下多少秒,从结果中可以看出还剩下96秒
127.0.0.1:6379> ttl mykey
(integer) 96
#重新更新该键的超时时间为20秒,从返回值可以看出该命令执行成功
127.0.0.1:6379> expire mykey 20
(integer) 1
#再用ttl确认一下,从结果中可以看出被更新了
127.0.0.1:6379> ttl mykey
(integer) 17
#立刻更新该键的值,以使其超时无效。
127.0.0.1:6379> set mykey "world"
OK
#从ttl的结果可以看出,在上一条修改该键的命令执行后,该键的超时也无效了
127.0.0.1:6379> ttl mykey
(integer) 1
127.0.0.1:6379> del mykey
(integer) 1
#添加不同类型的测试数据
127.0.0.1:6379> set mykey 2
OK
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> zadd myzset 1 "one" 2 "two"
(integer) 2
127.0.0.1:6379> hset myhash username "tom"
(integer) 1
#分别查看数据的类型
127.0.0.1:6379> type mykey
string
127.0.0.1:6379> type mylist
list
127.0.0.1:6379> type myset
set
127.0.0.1:6379> type myzset
zset
127.0.0.1:6379> type myhash
hash
#返回数据库中的任意键
127.0.0.1:6379> randomkey
"oldkey"
#清空当前打开的数据库
127.0.0.1:6379> flushdb
OK
#由于没有数据了,因此返回nil
127.0.0.1:6379> randomkey
(nil)
和其它数据库一样,Redis作为NoSQL数据库也同样提供了事务机制。在redis中,MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事务的基石。redis中事务的特征:
# 1. 事务被正常执行
#在当前连接上启动一个新的事务
127.0.0.1:6379> multi
OK
#执行事务中的第一条命令,从该命令的返回结果可以看出,该命令并没有立即执行,而是存于事务的命令队列
127.0.0.1:6379> incr t1
QUEUED
#又执行一个新的命令,从结果可以看出,该命令也被存于事务的命令队列
127.0.0.1:6379> incr t2
QUEUED
#执行事务命令队列中的所有命令,从结果可以看出,队列中命令的结果得到返回
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
#只有当提交事务后,在其他连接中才能看到变化
# 2. 事务中存在失败的命令
#开启一个新的事务
127.0.0.1:6379> multi
OK
#设置键a的值为string类型的3
127.0.0.1:6379> set a 3
QUEUED
#从键a所关联的值的头部弹出元素,由于该值是字符串类型,而lpop命令仅能用于List类型,因此在执行exec命令时,该命令将会失败
127.0.0.1:6379> lpop a
QUEUED
#再次设置键a的值为字符串4
127.0.0.1:6379> set a 4
QUEUED
#获取键a的值,以便确认该值是否被事务中的第二个set命令设置成功
127.0.0.1:6379> get a
QUEUED
#从结果中可以看出,事务中的第二条命令lpop执行失败,而其后的set和get命令均执行成功,这一点是Redis的事务与关系型数据库中的事务之间最为重要的差别
127.0.0.1:6379> exec
1) OK
2) (error) ERR Operation against a key holding the wrong kind of value
3) OK
4) "4"
# 3. 若在事务队列中存在命令性错误(类似于java编译性错误),则执行EXEC命令时,所有命令都不会执行
#开启一个新的事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
# 错误命令
127.0.0.1:6379> getset k1
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors
# 4. 回滚事务
#为键t2设置一个事务执行前的值
127.0.0.1:6379> set t2 tt
OK
#开启一个事务
127.0.0.1:6379> multi
OK
#在事务内为该键设置一个新值
127.0.0.1:6379> set t2 ttnew
QUEUED
#放弃事务
127.0.0.1:6379> discard
OK
#查看键t2的值,从结果中可以看出该键的值仍为事务开始之前的值
127.0.0.1:6379> get t2
"tt"
Jedis是一个封装了redis的java客户端,集成了redis的一些命令操作,并提供了连接池管理功能
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
public void test01(){
//获取jedis的连接
Jedis jedis=new Jedis("192.168.10.131",6379);
//验证
jedis.auth("itany");
//操作redis
jedis.set("name","tom");
jedis.set("password","123","nx");
System.out.println(jedis.get("name"));
jedis.lpush("mylist","jack","alice","mike");
System.out.println(jedis.lrange("mylist",0,1));
jedis.sadd("myset","aaa","bbb","ccc");
System.out.println(jedis.smembers("myset"));
System.out.println();
jedis.zadd("myzset",10,"a");
jedis.zadd("myzset",20,"b");
jedis.zadd("myzset",15,"c");
System.out.println(jedis.zrange("myzset",0,1));
System.out.println();
jedis.hset("user","name","alice");
jedis.hset("user","age","21");
Set<String> keys = jedis.hkeys("user");
for (String key:keys){
System.out.println(key+"="+jedis.hget("user",key));
}
Set<String> keys = jedis.keys("*");
System.out.println(keys);
//关闭连接
jedis.close();
}
有哪写的不够好,欢迎大佬们可以提出来,小弟会进行修改,谢谢观看。