# 保存数据set k1 china #保存k1字段值为china,这个数据必须设置,否则报错,第一次相当于添加#当再次进行操作时,就是重新设置,相当于修改#且无论是否加引号,都默认引号里面的数据,但不能少引号以及不是同一个引号,否则报错# 获取数据
get k1 #获取china数据,一般由""包括,如"china"(而git则默认消除""),而没有字段的则返回(nil),相当于空值#若是有两个引号的,则都默认加上"",使得不是一个引号里面的数据(包括引号了)
vim /opt/redis-5.0.4/redis.conf
#使用底行模式,输入/database,找到对应配置,即
databases 16#默认16个数据库,其中编号从0开始,到15(数据库数量-1),即#我们在客户端里进行操作数据时,默认一开始是0号数据库,可以通过如下命令,进行数据库的切换select16#切换到16号,数据库,出现(error) ERR DB index is out of range 数据库的下标超出了范围
测试:
127.0.0.1:6379> get k1 # 查询k1"china"#前面操作过的127.0.0.1:6379>select16# 切换16号数据库(error) ERR DB index is out of range # 数据库的下标超出了范围127.0.0.1:6379>select15# 切换15号数据库
OK
127.0.0.1:6379[15]> get k1 # 查询k1(nil)127.0.0.1:6379[15]>select0# 切换0号数据库
OK
127.0.0.1:6379> get k1 # 查询k1"china"
数据库键的数量(在客户端下操作):
dbsize
#查询的是键的数量,一般我们操作set o h,时,会加一个键,即o键,则对应数量增加1,redis一开始一般默认0个键
keys * #查询有那些键
127.0.0.1:6379[3]>set k1 v1 # 保存k1,这里只有这一个
OK #操作成功127.0.0.1:6379[3]> ttl k1 # 查看k1的过期时间,默认为-1,即永不过期,除非设置了(integer)-1#永不过期127.0.0.1:6379[3]> expire k1 10# 设置k1的过期时间为10秒(10秒后自动销毁)(integer)1#设置成功127.0.0.1:6379[3]> ttl k1 # 等待一下,然后查看k1的过期时间,发现还有7秒过期#这个等待和下面的等待看你决定等待多久(integer)7#还有7秒过期127.0.0.1:6379[3]> ttl k1 # 再等待一下,然后查看k1的过期时间,发现还有5秒过期(integer)5#还有5秒过期127.0.0.1:6379[3]> ttl k1 # 再等待一下,然后查看k1的过期时间,发现已经过期了(integer)-2#已过期127.0.0.1:6379[3]> get k1 # 这时看一看k1是否存在(nil)#发现不存在了127.0.0.1:6379[3]> keys * #再看一看对应的键(empty list or set)#若有其他键,自然会显示,但是在这之前只有k1这一个键,所以显示这个提示#发现没有键了(因为在这之前只有一个键),即不存在对应键了,相当于删除或者说从内存中销毁了对应键
type key:查看键的数据类型:
测试:
127.0.0.1:6379[9]>set kk jj #设置或保存键和对应值
OK #操作成功127.0.0.1:6379[9]> keys * #查看所有的键1)"kk"127.0.0.1:6379[9]> get kk #获取对应键的值"jj"127.0.0.1:6379[9]>type kk #上面的命令和返回结果前面有说明过,就不再说明了
string # kk的数据类型是会string字符串,若没有对应的kk,一般会返回none
使用Redis:
五大数据类型:
操作文档:http://redisdoc.com/
字符串String:
set,get,del,append,strlen(这一组命令):
测试:
127.0.0.1:6379>set k1 v1 # 保存数据
OK
127.0.0.1:6379>set k2 v2 # 保存数据
OK
127.0.0.1:6379> keys *
1)"k1"2)"k2"127.0.0.1:6379> del k2 # 删除数据k2,也可以指定多个,如del k2 k1,删除两个,那么返回就是2(integer)1#返回1(删除1个),删除成功127.0.0.1:6379> keys *
1)"k1"#没有k2了127.0.0.1:6379> get k1 # 获取数据k1"v1"127.0.0.1:6379> append k1 abc # 往k1的值追加数据abc(integer)5# 返回值的长度(字符数量)127.0.0.1:6379> get k1
"v1abc"#正好是5个字符127.0.0.1:6379> strlen k1 # 返回k1值的长度(字符数量)(integer)5#返回5个字符
incr,decr,incrby,decrby(这一组命令):加减操作,操作的必须是数字类型
incr:意思是increment,增加
decr:意思是decrement,减少
测试:
127.0.0.1:6379>set k1 1# 初始化k1的值为1
OK
127.0.0.1:6379> incr k1 # k1自增1(相当于java的k1++)(integer)2#返回操作后的数,注意k1需要是数字类型(也就是数字字符串),否则报错127.0.0.1:6379> incr k1
(integer)3127.0.0.1:6379> get k1
"3"127.0.0.1:6379> decr k1 # k1自减1(相当于java的k1--),#注意:一般这样的redis内部的加减操作是原子的(这里的),也就是自带的操作锁的功能,这是redis的原因,至于其他的的操作,通常也是如此(并不一定),具体可以百度查看#一般incr、incrby、decr、decrby都是原子的,一般来说,redis在设置数据这一块,必然是只能允许一人进入(任何一人进入的都是锁的操作,也就是单个线程操作,简称单线程),由于多路复用,那么其他像读取这一块,一般可以多人进入(integer)2#返回操作后的数据127.0.0.1:6379> decr k1
(integer)1127.0.0.1:6379> get k1
"1"127.0.0.1:6379> incrby k1 3# k1自增3(相当于java的k1+=3)#只能是整数,小数或者其他数(如字母)以及不完整数或者不合理数(如06,5.)不可,否则报错(integer)4#返回操作后的数据127.0.0.1:6379> get k1
"4"127.0.0.1:6379> decrby k1 2# k1自减2(相当于java的k1-=3)#只能是整数,小数或者其他数(如字母)以及不完整数或者不合理数(如06,5.)不可,否则报错(integer)2#返回操作后的数据127.0.0.1:6379> get k1
"2"#注意:对应的值必须只能是整数,小数或者其他数(如字母)以及不完整数或者不合理数(如06,5.)不可#否则incr,decr,incrby,decrby,操作不了,即报错
127.0.0.1:6379>set k1 abcdef # 初始化k1的值为abcdef
OK
127.0.0.1:6379> get k1
"abcdef"127.0.0.1:6379> getrange k1 0-1# 查询k1全部的值,负数代表从左边数数,正数代表从右边叔叔,其中a字符的下标代表0,那么f的下标就代表-1或者5# 但是这个5是需要知道对应长度的,所以一般我们操作-1来查询对应的全部值操作,都包括两边"abcdef"127.0.0.1:6379> getrange k1 03# 查询k1的值,范围是下标0~下标3(包含0和3,共返回4个字符)"abcd"127.0.0.1:6379> setrange k1 1 xxx # 替换k1的值,从下标1开始提供为xxx#即从下标1开始,根据替换的字符长度,将原来的从下标1开始的后面相应长度进行替换(包括下标1)#如果后面没有字符了,则添加上,如下(integer)6#返回操作后的对应的字符串长度127.0.0.1:6379> get k1
"axxxef"
setex,setnx(这一组命令)
set with expir(英文意思:使用Expire设置),即setex
理解的意思:添加数据的同时设置生命周期
测试:
127.0.0.1:6379> setex k1 5 v1 # 添加k1 v1数据的同时,设置5秒的声明周期
OK
127.0.0.1:6379> get k1
"v1"127.0.0.1:6379> get k1
(nil)# 等待一下,再次获取,发现已过期,k1的值v1自动销毁,相当于使用了del k1
set if not exist(英文意思:如果不存在则设置),即setnx
理解的意思:添加数据的时候判断是否已经存在,防止已存在的数据被覆盖掉
测试:
127.0.0.1:6379> setnx k1 sun
(integer)0# 返回0,添加失败,因为k1已经存在,这是为了解决set命令覆盖数据的127.0.0.1:6379> get k1
"laosun"127.0.0.1:6379> setnx k2 sun
(integer)1# 返回1,k2不存在,所以添加成功127.0.0.1:6379> get k2
"sun"
127.0.0.1:6379> sadd set01 12345(integer)5127.0.0.1:6379> sadd set02 x y z
(integer)3127.0.0.1:6379> smove set01 set02 3# 将set01中的元素3移动到set02中(integer)1# 移动成功,若这个3不存在,一般就会返回0,即移动失败#注意:若移动的是数字字符串,那么基本就是根据大写,若是字母,可能对方集合会进行随机排列#当然,这是根据自身与原来做比较,而进行的操作(每次操作后)
数学集合类:
集:sinter
并集:sunion
差集:sdiff
测试:
127.0.0.1:6379> sadd a 1234(integer)4127.0.0.1:6379> sadd b 3456(integer)4127.0.0.1:6379> smembers a
1)"1"2)"2"3)"3"4)"4"127.0.0.1:6379> smembers b
1)"3"2)"4"3)"5"4)"6"127.0.0.1:6379> sinter a b # a和b共同存在的元素1)"3"2)"4"127.0.0.1:6379> sunion a b # 将a和b中所有元素合并起来(排除重复的)1)"1"2)"2"3)"3"4)"4"5)"5"6)"6"#上面两个无论怎么交换位置,结果基本都一样127.0.0.1:6379>sdiff a b # 在a中存在,在b中不存在1)"1"2)"2"127.0.0.1:6379>sdiff b a # 在b中存在,在a中不存在1)"5"2)"6"127.0.0.1:6379>sdiff a
1)"1"2)"2"3)"3"4)"4"127.0.0.1:6379> sunion a
1)"1"2)"2"3)"3"4)"4"127.0.0.1:6379> sinter a
1)"1"2)"2"3)"3"4)"4"#上面单独的,基本就是相当于直接使用smembers a127.0.0.1:6379> sinter aa
(empty list or set)127.0.0.1:6379> sunion aa
(empty list or set)127.0.0.1:6379>sdiff aa
(empty list or set)#smembers aa自然是空的,因为没有127.0.0.1:6379>sdiff aa b
(empty list or set)127.0.0.1:6379>sdiff aa a
(empty list or set)127.0.0.1:6379>sdiff a aa
1)"1"2)"2"3)"3"4)"4"#与null做比较,自然sdiff a aa可以,a中存在,aa中不存在,那么就是a127.0.0.1:6379> sinter a aa
(empty list or set)127.0.0.1:6379> sinter aa a
(empty list or set)#与null做比较,都不可以,因为他们没有公有的数据127.0.0.1:6379> sunion a aa
1)"1"2)"2"3)"3"4)"4"127.0.0.1:6379> sunion aa a
1)"1"2)"2"3)"3"4)"4"#与null做比较,都可以,因为他们共同的数据就是a#总结:#sinter:两者之间共同存在的数据#sunion:两者合并的数据#sdiff:左边参数(集合)存在的数据,而右边参数(集合)不存在的数据
127.0.0.1:6379> hset a i 1000# 添加a,值为i=1000,不是这样的格式,一般会报错(integer)1#返回1,添加成功127.0.0.1:6379> hget a #必须指定键中的key(error) ERR wrong number of arguments for'hget'command127.0.0.1:6379> hget i #必须指定键中的key(error) ERR wrong number of arguments for'hget'command127.0.0.1:6379> hget a i #必须指定键中的key"1000"#返回key的value值127.0.0.1:6379> hget a 1000#不能指定value,必须指定键,即1000当成键了,因为这个参数就会去找键(nil)127.0.0.1:6379> hmset i a 1000 b 1002#进行多次添加key-value
OK #添加成功127.0.0.1:6379> hget i a #得到对应键的key的value值"1000"#返回value值127.0.0.1:6379> hmget i a b #进行多次读取,需要指定对应键,因为这个参数就会去找键1)"1000"2)"1002"#即键的值,存放key-value格式的数据,且是集合,即可以放多个127.0.0.1:6379> hgetall i #得到键的所有信息,即key-value依次的信息1)"a"#key2)"1000"#value,与上面一起,下面以此类推3)"b"4)"1002"127.0.0.1:6379> hdel i a #删除对应key为a的数据(integer)1#删除成功127.0.0.1:6379> hgetall i
1)"b"2)"1002"127.0.0.1:6379> hset k 90#当再次进行添加时,自然的是进行多次添加,但是需要是key-value的格式,否则报错(error) ERR wrong number of arguments for'hset'command127.0.0.1:6379> hset i k 90#当再次进行添加时,多出了对应的数据(integer)1#添加成功127.0.0.1:6379> hgetall i
1)"b"2)"1002"3)"k"4)"90"127.0.0.1:6379> hset i b 999#修改存在的key(integer)0#这里返回0,代表没有添加,但实际上却是修改成功127.0.0.1:6379> hgetall i
1)"b"2)"999"3)"k"4)"90"#从这里发现,无论什么集合或者对应的数据类型,都需要有一个键存在,这个键可以看成当前数据库的字段#不是表,这个redis数据库可以看成一个表,该键的值,可以用集合代表多条数据#根据前面的学习,发现这个字段基本是可以随便加的
hlen:返回元素的属性个数:
测试:
127.0.0.1:6379> hgetall i
1)"b"2)"999"3)"k"4)"90"127.0.0.1:6379> hlen i #查询集合的key个数,这里也就是元素的个数(integer)2#key的数量,即b和k这两个属性
hexists:判断元素是否存在某个属性:
测试:
127.0.0.1:6379> hgetall i
1)"b"2)"999"3)"k"4)"90"127.0.0.1:6379> hexists i b # i中是否存在b属性(integer)1#返回1,代表存在127.0.0.1:6379> hexists i bb # i中是否存在bb属性(integer)0#返回0,代表不存在
hkeys,hvals(这一组命令):获得属性的所有key/获得属性的所有value:
测试:
127.0.0.1:6379> hgetall i
1)"b"2)"999"3)"k"4)"90"127.0.0.1:6379> hkeys i # 获取i所有的属性名1)"b"2)"k"127.0.0.1:6379> hvals i # 获取i所有属性的值(内容)1)"999"2)"90"
现在我们看看对应添加key-value是否有顺序:
测试:
127.0.0.1:6379> hset o d 1000(integer)1127.0.0.1:6379> hset o a 1000(integer)1127.0.0.1:6379> hset o b 1000(integer)1127.0.0.1:6379> hset o 11000(integer)1127.0.0.1:6379> hset o 21000(integer)1127.0.0.1:6379> hset o 61000(integer)1127.0.0.1:6379> hset o 41000(integer)1127.0.0.1:6379> hgetall o
1)"d"2)"1000"3)"a"4)"1000"5)"b"6)"1000"7)"1"8)"1000"9)"2"10)"1000"11)"6"12)"1000"13)"4"14)"1000"#我们发现他就是直接从头到尾的插入表,并没有进行排列
hincrby,hincrbyfloat(这一组命令):自增(整数)/自增(小数):
测试:
127.0.0.1:6379> hset i a 10 b 20(integer)2127.0.0.1:6379> hgetall i
1)"a"2)"10"3)"b"4)"20"127.0.0.1:6379> hincrby i a #必须指定一个参数进行操作,没有默认的value++,否则报错(error) ERR wrong number of arguments for'hincrby'command127.0.0.1:6379> hincrby i a 1# 自增整数2,相当于即a这个key的value+=1(integer)11127.0.0.1:6379> hgetall i
1)"a"2)"11"#加1了3)"b"4)"20"127.0.0.1:6379> hincrby i a 5.5#只能是整数,小数或者其他数(如字母)以及不完整数或者不合理数(如06,5.)不可,否则报错(error) ERR value is not an integer or out of range
127.0.0.1:6379> hincrbyfloat i a 5.5#可以是整数,小数以及不完整数(如06,5.),但不可以是对应其他数(如字母),否则报错"16.5"#返回操作后的数据127.0.0.1:6379> hgetall i
1)"a"2)"16.5"3)"b"4)"20"127.0.0.1:6379> hincrbyfloat i a 5"21.5"127.0.0.1:6379> hincrbyfloat i a 5. #当成5来看"26.5"127.0.0.1:6379> hincrbyfloat i a 07 #当成7来看"33.5"127.0.0.1:6379> hincrbyfloat i a a #不可以是字母,即这里报错了(error) ERR value is not a valid float
127.0.0.1:6379> hgetall i
1)"a"2)"33.5"3)"b"4)"20"
hsetnx:添加的时候,先判断是否存在:
测试:
127.0.0.1:6379> flushdb #先情况当前数据库键,即信息,操作时一般都会先这样进行操作
OK
127.0.0.1:6379> hsetnx i a 10# 添加时,判断a是否存在(integer)1#添加成功,即不存在127.0.0.1:6379> hgetall i
1)"a"2)"10"127.0.0.1:6379> hsetnx i a 10(integer)0#添加失败,即存在127.0.0.1:6379> hsetnx i a 11(integer)0#添加失败,即存在127.0.0.1:6379> hgetall i
1)"a"2)"10"#数据没有变化127.0.0.1:6379> hset i a 11#直接设置数据(integer)0#没有添加,但修改了127.0.0.1:6379> hgetall i
1)"a"2)"11"#数据改变
在这里提醒一下,若加入中文会怎么样(String和List和Set和Hash):
测试:
127.0.0.1:6379>set a 和
OK
127.0.0.1:6379> get a
"\xe5\x92\x8c"127.0.0.1:6379> lpush b 和
(integer)1127.0.0.1:6379> lrange b 0-11)"\xe5\x92\x8c"127.0.0.1:6379> sadd c 和
(integer)1127.0.0.1:6379> smembers c
1)"\xe5\x92\x8c"127.0.0.1:6379> hset d key 和
(integer)1127.0.0.1:6379> hgetall d
1)"key"2)"\xe5\x92\x8c"#我们可以发现,上面四种数据类型,都可以添加中文#但都不能解决乱码,即对应的乱码应该与redis自身有关,造成显示时的乱码
127.0.0.1:6379> zadd a 10 v1 20 v2 30 v3 40 v4 50 v5 #进行添加数据(integer)5#返回添加的数量127.0.0.1:6379> zrange a 0-1#查询对应的属性,或者说key1)"v1"2)"v2"3)"v3"4)"v4"5)"v5"127.0.0.1:6379> zrange a 0-1 withscores #顺便查询出对应的值,或者说value1)"v1"2)"10"3)"v2"4)"20"5)"v3"6)"30"7)"v4"8)"40"9)"v5"10)"50"127.0.0.1:6379> zrangebyscore a 2040# 相当于20 <= value <= 401)"v2"2)"v3"3)"v4"127.0.0.1:6379> zrangebyscore a 20(40# 相当于20 <= value < 401)"v2"2)"v3"127.0.0.1:6379> zrangebyscore a (20(40# 相当于20 < value < 401)"v3"127.0.0.1:6379> zrangebyscore a 1040 limit 22# 10 <= value <= 40,共返回四个,跳过前2个,取2个1)"v3"2)"v4"127.0.0.1:6379> zrangebyscore a 1040 limit 22 withscores
# 10 <= score <= 40,共返回四个,跳过前2个,取2个,并显示对应value1)"v3"2)"30"3)"v4"4)"40"127.0.0.1:6379> zrangebyscore a 1040 withscores limit 22#换个位置也可以,与Linux的类似1)"v3"2)"30"3)"v4"4)"40"127.0.0.1:6379> zrangebyscore a 1040 withscores limit 21# 10 <= score <= 40,共返回四个,跳过前2个,取1个,并显示对应value1)"v3"2)"30"127.0.0.1:6379> zrangebyscore a 1040 withscores limit
#需要指定对应范围,且要完整,即不指定或者指定一个都报错(error) ERR syntax error
127.0.0.1:6379> zrangebyscore a 1040 withscores
#这里我们就直接查询范围里面的了,发现前面的limit 2 1的确是将前面两个跳过,且只取得一个,即v31)"v1"2)"10"3)"v2"4)"20"5)"v3"6)"30"7)"v4"8)"40"127.0.0.1:6379> zrangebyscore a 1040 withscores limit 26#当取的数据取完后,就不会再取了#即若大于等于后续的属性,则就是后面的所有属性1)"v3"2)"30"3)"v4"4)"40"127.0.0.1:6379> zrangebyscore a 1040 withscores limit 46#忽略前面所有的自然就是没得取了(empty list or set)127.0.0.1:6379> zrangebyscore a 1040 withscores limit 36#正好取得一个1)"v4"2)"40"
zrem:删除元素:
测试:
127.0.0.1:6379> zrange a 0-11)"v1"2)"v2"3)"v3"4)"v4"5)"v5"127.0.0.1:6379> zrange a -10#实际上进行取数据都是从左到右的,其他数据类型基本如此(empty list or set)127.0.0.1:6379> zrem a v2 # 移除v2(integer)1#删除成功127.0.0.1:6379> zrange a 0-11)"v1"2)"v3"3)"v4"4)"v5"
127.0.0.1:6379> zrange a 0-11)"v1"2)"v3"3)"v4"4)"v5"127.0.0.1:6379> zcard a # 集合中元素的个数(integer)4#返回对应的个数127.0.0.1:6379> zrange a 0-1 withscores
1)"v1"2)"10"3)"v3"4)"30"5)"v4"6)"40"7)"v5"8)"50"127.0.0.1:6379> zcount a 3050# 分数在30~50之间(包括30和50),共有几个元素(integer)3#返回对应的个数,正好是v3,v4,v5127.0.0.1:6379> zcount a 5060#只有50这一个(integer)1#返回一个127.0.0.1:6379> zcount a 50#必须完整,否则报错(error) ERR wrong number of arguments for'zcount'command127.0.0.1:6379> zcount a #必须完整,否则报错#实际上由于没有必须完整造成报错的,是因为命令是各式是固定的,而有些参数是可加的,如withscores#而不可以加的,则必须写上(error) ERR wrong number of arguments for'zcount'command127.0.0.1:6379> zrank a v4 # v4在集合中的下标(从上向下,从左到右)(integer)2#正好是2127.0.0.1:6379> zscore a v4 # 通过元素获得对应的分数"40"#返回对应分数
zrevrank:逆序找下标(从下向上):
测试:
127.0.0.1:6379> zrange a 0-1 withscores
1)"v1"2)"10"3)"v3"4)"30"5)"v4"6)"40"7)"v5"8)"50"127.0.0.1:6379> zrevrank a v4 #反过来找下标,若是正过来找就是2,而反过来找,就是1(integer)1#返回逆序下标,这里就是1
zrevrange:逆序查询:
测试:
127.0.0.1:6379> zrange a 0-11)"v1"2)"v3"3)"v4"4)"v5"127.0.0.1:6379> zrevrange a 0-1#逆序查询,相当于从最后开始算下标,且从最后找,所有任然是从小到大1)"v5"2)"v4"3)"v3"4)"v1"
zrevrangebyscore:逆序范围查找:
测试:
127.0.0.1:6379> zrevrange a 0-1 withscores
1)"v5"2)"50"3)"v4"4)"40"5)"v3"6)"30"7)"v1"8)"10"127.0.0.1:6379> zrevrangebyscore a 3010# 逆序查询分数在30~20(包括30和20)之间的 (注意,先写大值,再写小值)1)"v3"2)"v1"127.0.0.1:6379> zrevrangebyscore a 1030#而正是逆序查询,所以是会从大的到小的#因为对应的数字由于下标从最后开始,使得从大到下形成的,否则就不是逆序查询了#所以需要大的在前,否则报错,即查询不到(因为连接不到),即返回null,集合的null(empty list or set)127.0.0.1:6379> zrangebyscore a 10301)"v1"2)"v3"127.0.0.1:6379> zrangebyscore a 3010#正如逆序查询一样,由于是正序查询,那么对应的是小的到大的,否则就是逆序查询了#所以需要小的在前,否则报错,像这种查询的,所有集合基本都遵循这样的解释#就如zrange a 0 -1 withscores中0 和-1的正查询(不可反过来,基本没有逆序查询操作)一样#其他集合也基本是一样的(其他集合基本没有逆序查询的操作,当然,若有则遵循逆序查询解释)(empty list or set)
#对应的配置
save 9001#满足从开启(客户端开启)开始计时,每过900秒#且其中至少发生了1次操作(如增删改等等操作,使得数据库数据变化),则存一次#然后继续从头计时,并记录上次计时的次数,除非判断成功,则消除次数,并重新计时,其中若记录了上次次数#则只会判断次数,而不会判断时间了(虽然也在计时)
save 12010#原来一般是save 300 10,这个配置这里进行了修改#满足从开启(客户端开启)开始计时,每过了120秒#且至少发生了10次操作(如增删改等等操作,使得数据库数据变化),则存一次#然后继续从头计时,并记录上次计时的次数,除非判断成功,则消除次数,并重新计时,其中若记录了上次次数#则只会判断次数,而不会判断时间了(虽然也在计时)#这里你可以将120改成20秒,并打开两个Linux窗口(记为1号窗口,2号窗口)#其中1号窗口使用ls --full-time命令进行查看dump.rdb文件日期#2号窗口开启redis客户端,操作两次数据#然后在1号窗口多次使用ls --full-time命令进行查看,大概过了20秒,这个日期就更新了#照着这样一路测试,若只操作1次,会发现,过了20秒并没有更新,接下来需要继续计时了#但是这时只要你在操作一次,就会立马更新
save 6010000#满足从开启(客户端开启)开始计时,每过了60秒#且至少发生了10000次操作(如增删改等等操作,使得数据库数据变化),则存一次#然后继续从头计时,并记录上次计时的次数,除非判断成功,则消除次数,并重新计时,其中若记录了上次次数#则只会判断次数,而不会判断时间了(虽然也在计时)#当他们满足时,那么会自动进行保存,即就算你没有关闭redis,也会进行保存#可以使用ls --full-time命令看(使用两个Linux窗口查看)#上面的满足从开启开始计时的意思:如我出去走走(开启)#假如在路上每走900秒,且900秒中间至少摇头了一次,则进行记录一下位置,这个900秒就是这个意思,然后继续这样#除非进行关闭redis,即shutdown命令,模拟关机#对应的解释:判断顺序是同时计时的,当有一个判断正确后,全部都重新计时#即我们的配置也未必是有顺序的,如第二个配置中120,可能对应的时间大点,如改成1200,反正都是同时进行#二者要必须同时满足,即操作次数和发生中间的总时间同时满足才可进行自动备份#可以使用ls --full-time命令,精确到秒级(即可以看到秒)
当然如果你只是用Redis的缓存功能,不需要持久化
那么你可以注释掉所有的 save 行来停用保存功能,也可以直接一个空字符串来实现停用:save “”
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379>set k1 v1
QUEUED # 加入队列,这时我们的命令执行就是加入队列了,无论是否对错127.0.0.1:6379>set k2 v2
QUEUED # 加入队列127.0.0.1:6379> get k2
QUEUED # 加入队列127.0.0.1:6379>set k3 v3
QUEUED # 加入队列127.0.0.1:6379>exec# 执行,一起成功!1) OK
2) OK
3)"v2"4) OK
#的确都是一路执行
一起不执行:
放弃之前的操作,恢复到原来的值
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379>set k1 v1111
QUEUED
127.0.0.1:6379>set k2 v2222
QUEUED
127.0.0.1:6379> discard # 放弃操作,或者说不执行了,并关闭事务
OK
127.0.0.1:6379> get k1
"v1"# 还是原来的值
一粒老鼠屎坏一锅汤 :
一句报错,全部取消,恢复到原来的值:
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)127.0.0.1:6379> multi
OK
127.0.0.1:6379>set11
QUEUED
127.0.0.1:6379>set22
QUEUED
127.0.0.1:6379>set111#出现不合理的数据,但是却并不会造成事务的结束,因为他还是操作了(可以识别),只是执行格式不对而已#可以识别的,基本可以执行,只是执行这个语句时,会报错
QUEUED
127.0.0.1:6379>exec1) OK
2) OK
3)(error) ERR syntax error
#由于并不会造成事务的结束,所有还会执行127.0.0.1:6379> keys *
1)"2"2)"1"127.0.0.1:6379> multi
OK
127.0.0.1:6379>set33
QUEUED
127.0.0.1:6379> setlalala
#出现不合理的数据,会造成事务的结束(执行时),因为识别不了#这里与mysql不同,mysql基本都会可以提交#因为对应识别不了基本不会使得事务出现问题,或者自动回滚(mysql的自动回滚),因为他是操作表的,而不是结果的(error) ERR unknown command`setlalala`, with args beginning with:
#出现了错误,即不是QUEUED,相当于使得提交执行时,执行不了127.0.0.1:6379>exec#由于有识别不了的,那么提交执行失败(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
1)"2"2)"1"127.0.0.1:6379> multi
OK
127.0.0.1:6379>set9999
QUEUED
127.0.0.1:6379> setlalala
(error) ERR unknown command`setlalala`, with args beginning with:
127.0.0.1:6379>exec#由于有识别不了的,那么提交执行失败,且其他的也不会执行(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
1)"2"2)"1"#发现的确没有执行127.0.0.1:6379> multi
OK
127.0.0.1:6379>set9999
QUEUED
127.0.0.1:6379> setlalala
(error) ERR unknown command`setlalala`, with args beginning with:
127.0.0.1:6379> discard #虽然识别不了,但是可以回滚,因为我们不执行
OK
127.0.0.1:6379> keys *
1)"2"2)"1"
冤有头债有主 :
追究责任,谁的错,找谁去:
127.0.0.1:6379> keys *
1)"a"127.0.0.1:6379> get a
"a"127.0.0.1:6379> multi
OK
127.0.0.1:6379>set66
QUEUED
127.0.0.1:6379> incr a
#可以识别,只是操作结果报错而已,类似java中的通过编译(识别不了就可以说是编译不通过),只是执行时报错#而mysql可以说没有编译这个环节,所有识别不了,还是可以执行
QUEUED
127.0.0.1:6379>exec1) OK #执行成功2)(error) ERR value is not an integer or out of range #报错了127.0.0.1:6379> keys *
1)"a"2)"6"
watch监控 :
测试:模拟收入与支出:
正常情况下:
127.0.0.1:6379>setin100# 收入100元
OK
127.0.0.1:6379>set out 0# 支出0元
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby in20# 收入-20
QUEUED
127.0.0.1:6379> incrby out 20# 支出+20
QUEUED
127.0.0.1:6379>exec1)(integer)80#收入-202)(integer)20#支出+20# 结果,没问题!127.0.0.1:6379> get in"80"127.0.0.1:6379> get out
"20"