点击上方编程牧马人,选择设为星标
优质项目,及时送达
-----
本系列讲述Redis基本操作以及与SpringBoot集成操作,基本操作包括基本数据类型,例如String、List、Set、Zset、Hash、Geospatial地理位置操作、Hyperloglog基数统计、Bitmap位图场景操作、redis基本事务操作等;集成操作包括自定义RedisTemplate、持久化、订阅发布、哨兵模式、主从复制等,本节介绍Redis基本操作,篇幅较长,建议手动收藏。
Redis基本数据类型操作[1]连接redis服务器:ubuntu
mario:/mnt/c/Users/admin$redis-server测试连接:ubuntu
mario:/mnt/c/Users/admin$redis-cli.0.0.1:pingPONG.0.0.1:性能测试★redis性能测试,个并发,每个并发000个请求
”redis-benchmark-hlocalhost-p-c-n000性能测试1性能测试2切换数据库
.0.0.1:select3OK.0.0.1:[3]DBSize##查看当前数据库大小(integer)0.0.0.1:[3]dbsize(integer)0.0.0.1:[3]setnamemarioOK.0.0.1:[3]getname"mario".0.0.1:[3]dbsize(integer)1.0.0.1:[3]select7OK.0.0.1:[7]getname(nil).0.0.1:[7]select3OK.0.0.1:[3]keys*##查看数据库所有的key1)"name".0.0.1:[3]flushdb##清除当前数据库OK.0.0.1:[3]flushall##清除全部数据库的内容OK.0.0.1:[3]keys*(emptylistorset)★
redis是单线程的,明白Redis是很快的,官方表示,Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!所有就使用了单线程了!Redis是C语言写的,官方提供的数据为000+的QPS,完全不比同样是使用key-vale的Memecache差!
”Redis为什么单线程还这么快?
1、误区1:高性能的服务器一定是多线程的?2、误区2:多线程(CPU上下文会切换!)一定比单线程效率高!先去CPU内存硬盘的速度要有所了解!核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
Redis-key.0.0.1:[3]keys*(emptylistorset).0.0.1:[3]setage1OK.0.0.1:[3]getage"1".0.0.1:[3]setnamemarioOK.0.0.1:[3]getnaem(nil).0.0.1:[3]getname"mario".0.0.1:[3]existsname(integer)1.0.0.1:[3]existsname1(integer)0.0.0.1:[3]movename1(integer)1.0.0.1:[3]getname(nil)==================================.0.0.1:[3]keys*(emptylistorset).0.0.1:[3]setage1OK.0.0.1:[3]getage"1".0.0.1:[3]setnamemarioOK.0.0.1:[3]getname"mario".0.0.1:[3]existsname#判断当前的key是否存在(integer)1.0.0.1:[3]existsname1(integer)0.0.0.1:[3]movename1#移除当前的key(integer)1.0.0.1:[3]getname(nil).0.0.1:[3]clear#清屏.0.0.1:[3]setnamexiaomingOK.0.0.1:[3]expirename10#设置key的过期时间,单位是秒(integer)1.0.0.1:[3]ttlname#查看当前key的剩余时间(integer)7.0.0.1:[3]getname"xiaoming".0.0.1:[3]ttlname(integer)3.0.0.1:[3]getname(nil).0.0.1:[3]typeage#查看当前key的一个类型!stringString类型
.0.0.1:[3]setnamexiaohongOK.0.0.1:[3]keys*1)"age"2)"name".0.0.1:[3]existskey(integer)0.0.0.1:[3].0.0.1:[3]existsname(integer)1.0.0.1:[3]appendname",xiaoming"#追加字符串,如果当前key不存在,就相当于setkey(integer)17.0.0.1:[3]getname"xiaohong,xiaoming".0.0.1:[3]strlenname#获取字符串的长度(integer)17.0.0.1:[3]appendname",xiaolan"(integer)25.0.0.1:[3]appendsex"boy"#追加字符串,如果当前key不存在,就相当于setkey(integer)3.0.0.1:[3]getsex"boy".0.0.1:[3]##########################################i++#步长i+=.0.0.1:[3]setviews0#初始浏览量为0OK.0.0.1:[3]getviews"0".0.0.1:[3]incrviews#自增1浏览量变为1(integer)1.0.0.1:[3]incrviews(integer)2.0.0.1:[3]getviews"2".0.0.1:[3]decrviews#自减1浏览量-1(integer)1.0.0.1:[3]decrviews(integer)0.0.0.1:[3]decrviews(integer)-1.0.0.1:[3]getviews"-1".0.0.1:[3]incrbyviews10#可以设置步长,指定增量!(integer)9.0.0.1:[3]incrbyviews10(integer)19.0.0.1:[3]decrbyviews5(integer)14.0.0.1:[3]decrbyviews5(integer)9############################################################字符窜范围range.0.0.1:[3]setkey1"hello,world"OK.0.0.1:[3]getkey1"hello,world".0.0.1:[3]getrangekey#截取字符串[0,3]"hell".0.0.1:[3]getrangekey10-1#获取全部的字符串和getkey是一样的"hello,world".0.0.1:[3]setkey2hello,world#双引号加或者不加都是字符窜OK.0.0.1:[3]getkey2"hello,world"########################################################替换.0.0.1:[3]setkey2abcdOK.0.0.1:[3]getkey2"abcd".0.0.1:[3]setrangekey21xx#替换指定位置下标开始的字符串!(integer)4.0.0.1:[3]getkey2"axxd"####################################################setex(setwithexpire)#设置过期时间#setnx(setifnotexist)#不存在设置(在分布式锁中会常常使用!).0.0.1:[3]setexkey"hello"#设置key3的值为hello,30秒后过期OK.0.0.1:[3]ttlkey3(integer)22.0.0.1:[3]getkey3"hello".0.0.1:[3]ttlkey3(integer)11.0.0.1:[3]setnxmykey"redis"#如果mykey不存在,创建mykey(integer)1.0.0.1:[3]getkey3(nil).0.0.1:[3]ttlkey3(integer)-2.0.0.1:[3]setnxmykey"mongodb"#如果mykey存在,创建失败!(integer)0.0.0.1:[3]getmykey"redis"################################################mset#mget.0.0.1:[3]msetk1v1k2v2k3v3#同时设置多个值OK.0.0.1:[3]keys*1)"views"2)"sex"3)"name2"4)"k3"5)"name"6)"k2"7)"k1"8)"age"9)"mykey"10)"name1"11)"key2"12)"key1".0.0.1:[3]mgetk1k2k3#同时获取多个值1)"v1"2)"v2"3)"v3".0.0.1:[3]msetnxk1v1k4v4#msetnx是一个原子性的操作,要么一起成功,要么一起失败(integer)0.0.0.1:[3]getk4(nil)############################################################对象设置#设置一个user:1对象值为json字符来保存一个对象!#这里的key是一个巧妙的设计:user:{id}:{filed},如此设计在Redis中是完全OK了!.0.0.1:[3]setuser:1{name:zhangsan,age:3}OK.0.0.1:[3]msetuser:1:namezhangsan1user:1:age2OK.0.0.1:[3]mgetuser:1:nameuser:1:age1)"zhangsan1"2)"2"############################################################getset.0.0.1:[3]getsetdbredis#如果不存在值,则返回nil,先get没有,在set(nil).0.0.1:[3]getdb#有了"redis".0.0.1:[3]getsetdbmongodb#如果存在值先返回原来的值,在设置新值"redis".0.0.1:[3]getdb#返回的是新值"mongodb"List(列表)
在redis里面,我们可以把list玩成栈、队列、阻塞队列!所有的list命令都是用l开头的,Redis不区分大小命令
.0.0.1:[3]lpushlistone#将一个值或者多个值,插入到列表头部(左)(integer)1.0.0.1:[3]lpushlist2(integer)2.0.0.1:[3]lpushlist3(integer)3.0.0.1:[3]lrangelist0-1#获取list中值!1)"3"2)"2"3)"one".0.0.1:[3]lrangelist)"3"2)"2".0.0.1:[3]rpushlistright#将一个值或者多个值,插入到列表尾部(右)(integer)4.0.0.1:[3]lrangelist0-11)"3"2)"2"3)"one"4)"right"############################################################lpop#rpop.0.0.1:[3]lpoplist"3".0.0.1:[3]rpoplist"right".0.0.1:[3]lrangelist0-11)"2"2)"one"############################################################lindex.0.0.1:[3]lindexlist1#通过下标获得list中的某一个值!"one".0.0.1:[3]lindexlist0"2"############################################################Llen.0.0.1:[3]lpushlistone(integer)3.0.0.1:[3]lpushlisttwo(integer)4.0.0.1:[3]Lpushlist3(integer)5.0.0.1:[3]llenlist#返回列表的长度(integer)5############################################################一出指定的值#取关uid#Lrem.0.0.1:[3]lrangelist0-11)"3"2)"two"3)"one"4)"2"5)"one".0.0.1:[3]lremlist1two#移除list集合中指定个数的value,精确匹配(integer)1.0.0.1:[3]lrangelist0-11)"3"2)"one"3)"2"4)"one".0.0.1:[3]lremlist1one(integer)1.0.0.1:[3]lremlist1one(integer)1.0.0.1:[3]lrangelist0-11)"3"2)"2".0.0.1:[3]lpushlist3(integer)3.0.0.1:[3]lrangelist0-11)"3"2)"3"3)"2".0.0.1:[3]lremlist23(integer)2.0.0.1:[3]lrangelist0-11)"2"############################################################trim修剪.0.0.1:[3]flushdbOK.0.0.1:[3]keys*(emptylistorset).0.0.1:[3]lpushmylistone(integer)1.0.0.1:[3]lpushmylisttwo(integer)2.0.0.1:[3]lpushmylistthree(integer)3.0.0.1:[3]lpushmylistfour(integer)4.0.0.1:[3]lrangemylist0-11)"four"2)"three"3)"two"4)"one".0.0.1:[3]ltrimmylist12#通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素OK.0.0.1:[3]lrangemylist0-11)"three"2)"two"###########################################################rpoplpush#移除列表的最后一个元素,将他移动到新的列表中!.0.0.1:[3]rpushmylist"hello"(integer)3.0.0.1:[3]rpushmylist"hello1"(integer)4.0.0.1:[3]rpushmylist"hello2"(integer)5.0.0.1:[3]lrangemylist0-11)"three"2)"two"3)"hello"4)"hello1"5)"hello2".0.0.1:[3]rpoplpushmylistmylist2#移除列表的最后一个元素,将他移动到新的列表中!"hello2".0.0.1:[3]lrangemylist0-11)"three"2)"two"3)"hello"4)"hello1".0.0.1:[3]lrangemylist20-11)"hello2"############################################################lset将列表中指定下标的值替换为另一个值,更新操作.0.0.1:[3]existslist#判断这个列表是否存在(integer)0.0.0.1:[3]lsetlist0item#如果不存在列表我们去更新就会报错(error)ERRnosuchkey.0.0.1:[3]lpushlistv1(integer)1.0.0.1:[3]lrangelist0-11)"v1".0.0.1:[3]lsetlist0item#如果存在,更新当前下标的值OK.0.0.1:[3]lrangelist0-11)"item".0.0.1:[3]lsetlist3v3#如果不存在则报错(error)ERRindexoutofrange############################################################linsert#将某个具体的value插入到列中某个元素的前面或者后面!.0.0.1:[3]rpushmylisthello(integer)1.0.0.1:[3]rpushmylistworld(integer)2.0.0.1:[3]linsertmylistbeforeworldother(integer)3.0.0.1:[3]lrangemylist0-11)"hello"2)"other"3)"world".0.0.1:[3]linsertmylistafterhelloanother(integer)4.0.0.1:[3]lrangemylist0-11)"hello"2)"another"3)"other"4)"world"小结实际上是一个链表,beforeNodeafter,left,right都可以插入值如果key不存在,创建新的链表如果key存在,新增内容如果移除了所有值,空链表,也代表不存在!在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点消息排队!消息队列(LpushRpop),栈(LpushLpop)Set(集合)★
set中的值不能重复!
”.0.0.1:[3]saddmysethello#set集合中添加(integer)1.0.0.1:[3]saddmysetworld(integer)1.0.0.1:[3]saddmysetmario(integer)1.0.0.1:[3]smembersmyset#查看指定set的所有值1)"mario"2)"world"3)"hello".0.0.1:[3]saddmysetone(integer)1.0.0.1:[3]saddmysettwo(integer)1.0.0.1:[3]smembersmyset#查看指定set的所有值无序!1)"mario"2)"one"3)"world"4)"hello"5)"two".0.0.1:[3]sismembermysetthree#判断某一个值是不是在set集合中!(integer)0.0.0.1:[3]sismembermysetone(integer)1.0.0.1:[3]scardmyset#获取set集合中的内容元素个数!(integer)5.0.0.1:[3]sremmysethello#移除set集合中的指定元素(integer)1.0.0.1:[3]smembersmyset1)"one"2)"mario"3)"two"4)"world"############################################################set无序不重复集合。抽随机!.0.0.1:[3]srandmembermyset#随机抽选出一个元素"one".0.0.1:[3]srandmembermyset"world".0.0.1:[3]srandmembermyset"mario".0.0.1:[3]srandmembermyset"world".0.0.1:[3]srandmembermyset21)"mario"2)"world"############################################################删除指定key,随机删除key.0.0.1:[3]spopmyset"world".0.0.1:[3]spopmyset"one".0.0.1:[3]smembersmyset1)"mario"2)"two"############################################################将一个指定的值移动到另外一个set集合.0.0.1:[3]saddmysethello(integer)1.0.0.1:[3]saddmysetworld(integer)1.0.0.1:[3]saddmysetthree(integer)1.0.0.1:[3]smovemysetmyset2hello(integer)1.0.0.1:[3]smovemysetmyset2hello00#不存在指定值则不移(integer)0.0.0.1:[3]smembersmyset1)"mario"2)"two"3)"three"4)"world".0.0.1:[3]smembersmyset21)"hello"############################################################集合共同