Redis中存储数据常用的数据类型主要有五种:String、List、Set、Sorted Set、Hash,这五种数据结构在Redis中存储数据的命令掌握对于我们后期在使用Java框架封装类操作Redis的API了解是非常重要的。所以在这里对这五种数据结构进行一一汇总,另外也简单介绍一下bitmaps、hyperloglogs、geospatial这三种类型。
String类型在Redis中常用的操作:
①get/set/exists/append/strlen命令:
127.0.0.1:6379> set key1 v1 # 设置值OK 127.0.0.1:6379> get key1 # 获取值"v1"127.0.0.1:6379> keys * # 获取所有的值1) "key1"127.0.0.1:6379> EXISTS key1 # 判断key1是否存在(integer) 1127.0.0.1:6379> APPEND key1 "hello" # 向key1中追加"hello",如果Key1不存在,那就相当于set key1(integer) 7127.0.0.1:6379> get key1"v1hello"127.0.0.1:6379> STRLEN key1 #获取字符串的长度(integer) 7127.0.0.1:6379> APPEND key1 ", fengye"(integer) 15127.0.0.1:6379> STRLEN key1(integer) 15127.0.0.1:6379> get key1"v1hello, fengye"
②自增/减、步长(浏览量、点击数):
# +1/-1与+n/-n127.0.0.1:6379> set views 0OK127.0.0.1:6379> get views"0"127.0.0.1:6379> incr views # 自增+1(integer) 1127.0.0.1:6379> incr views(integer) 2127.0.0.1:6379> get views"2"127.0.0.1:6379> decr views # 自减-1(integer) 1127.0.0.1:6379> decr views(integer) 0127.0.0.1:6379> decr views(integer) -1127.0.0.1:6379> get views"-1"127.0.0.1:6379> INCRBY views 10 # 增加 n(integer) 9127.0.0.1:6379> INCRBY views 10(integer) 19127.0.0.1:6379> DECRBY views 5 # 减少 n(integer) 14
③字符串截取:
127.0.0.1:6379> set key1 "hello, fengye"OK127.0.0.1:6379> get key1"hello, fengye"127.0.0.1:6379> GETRANGE key1 0 4 # 截取闭区间 [0, 4]的字符串"hello"127.0.0.1:6379> GETRANGE key1 0 -1 # 截取全部的字符串,和get key1同理"hello, fengye"
④替换:
127.0.0.1:6379> set key2 abcddefgOK127.0.0.1:6379> get key2"abcddefg"127.0.0.1:6379> SETRANGE key2 2 XXX # 替换指定位置开始的字符串(integer) 8127.0.0.1:6379> get key2"abXXXefg"
⑤setex(set with expire)与setnx(set if not exist):
#setex :设置过期时间#setnx :不存在当前key才会设置值,在分布式锁中常常使用127.0.0.1:6379> setex key3 30 "hello" # 设置过期时间为30s,30s后过期OK127.0.0.1:6379> ttl key3(integer) 21127.0.0.1:6379> get key3"hello"127.0.0.1:6379> setnx mykey "redis" #设置mykey的值为redis,当mykey不存在时设置成功(integer) 1127.0.0.1:6379> keys *1) "key1"2) "key2"3) "mykey"127.0.0.1:6379> ttl key3(integer) -2127.0.0.1:6379> setnx mykey "mongoDb" #当mykey已经存在了,设置mykey会失败(integer) 0127.0.0.1:6379> get mykey"redis"
⑥同时设置多个值mset/mget/msetnx:
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 #同时设置多个值OK127.0.0.1:6379> keys *1) "k3"2) "k2"3) "k1"127.0.0.1:6379> mget k1 k2 k3 #同时获取多个值1) "v1"2) "v2"3) "v3"127.0.0.1:6379> msetnx k1 y1 k4 v4 #同时获取多个值,msetnx是一个原子性操作,要么一起成功,要么一起失败(integer) 0 127.0.0.1:6379> get k4 (nil)
⑦设置对象的值:
127.0.0.1:6379> set user:2 {name:lisi,age:3} # 使用json字符串来保存user的值OK127.0.0.1:6379> get user:2"{name:lisi,age:3}"127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2 # 使用user:1:name与user1:1:age来保存值,user:{id}:{field}作为key来保存值OK127.0.0.1:6379> mget user:1:name user:1:age1) "zhangsan"2) "2"
⑧getset(先获取后设置):
127.0.0.1:6379> getset db redis #如果不存在值,则返回nil,并设置初始值(nil)127.0.0.1:6379> get db"redis"127.0.0.1:6379> getset db mongodb #如果存在值,则返回那个值,并设置新的值"redis"127.0.0.1:6379> get db"mongodb"
①lpush/rpush/lrange(压栈):
127.0.0.1:6379> LPUSH list one # 将一个或多个值放到列表的头部(左push)(integer) 1127.0.0.1:6379> LPUSH list two(integer) 2127.0.0.1:6379> LPUSH list three(integer) 3127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"3) "one"127.0.0.1:6379> LRANGE list 0 11) "three"2) "two"127.0.0.1:6379> RPUSH list four # 将一个或多个值放到列表的尾部(右push)(integer) 4127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"3) "one"4) "four"
②lpop/rpop:
127.0.0.1:6379> LPOP list # 左移除列表中的一个元素"three"127.0.0.1:6379> RPOP list # 右移除列表中的一个元素"four"127.0.0.1:6379> LRANGE list 0 -11) "two"2) "one"
③lindex(list index的简写):
127.0.0.1:6379> LINDEX list 1 # 通过下标获得list中的某一个值"one"127.0.0.1:6379> LINDEX list 0"two"
④llen:
127.0.0.1:6379> LPUSH list one(integer) 1127.0.0.1:6379> LPUSH list two(integer) 2127.0.0.1:6379> LPUSH list three(integer) 3127.0.0.1:6379> Llen list # 返回列表的长度(integer) 3
⑤Lrem:
127.0.0.1:6379> LRANGE list 0 -11) "three"2) "three"3) "two"4) "one"127.0.0.1:6379> lrem list 1 one # 移除list集合中指定个数的元素,精确匹配个数并移除(integer) 1127.0.0.1:6379> LRANGE list 0 -11) "three"2) "three"3) "two"127.0.0.1:6379> lrem list 1 three(integer) 1127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"127.0.0.1:6379> LPUSH list three(integer) 3127.0.0.1:6379> lrem list 2 three(integer) 2127.0.0.1:6379> LRANGE list 0 -11) "two"
⑥Lrem:
127.0.0.1:6379> Rpush mylist "hello"(integer) 1127.0.0.1:6379> Rpush mylist "hello1"(integer) 2127.0.0.1:6379> Rpush mylist "hello2"(integer) 3127.0.0.1:6379> Rpush mylist "hello3"(integer) 4127.0.0.1:6379> Ltrim mylist 1 2 # 通过下标截取指定的长度,截取之后List会被改变,只剩下截取后的元素OK127.0.0.1:6379> LRANGE list 0 -1(empty list or set)127.0.0.1:6379> LRANGE mylist 0 -11) "hello1"2) "hello2"
⑦rpoplpush:
127.0.0.1:6379> rpush mylist "hello"(integer) 1127.0.0.1:6379> rpush mylist "hello1"(integer) 2127.0.0.1:6379> rpush mylist "hello2"(integer) 3127.0.0.1:6379> rpoplpush mylist myotherlist #右弹栈,移除列表中最后一个元素并放入新的列表元素中"hello2"127.0.0.1:6379> lrange mylist 0 -11) "hello"2) "hello1"127.0.0.1:6379> lrange myotherlist 0 -11) "hello2"
⑧lset:
lset:将列表中指定下标的一个元素替换成另外一个元素,更新操作
127.0.0.1:6379> EXISTS list(integer) 0127.0.0.1:6379> lset list 0 item #判断列表是否存在,如果不存在的话,当前更新会报错(error) ERR no such key127.0.0.1:6379> lpush list value1(integer) 1127.0.0.1:6379> LRANGE list 0 01) "value1"127.0.0.1:6379> lset list 0 item #如果列表已经存在元素,可以更新当前列表中的元素OK127.0.0.1:6379> LRANGE list 0 01) "item"127.0.0.1:6379> lset list 1 other #如果更新范围超出限制,也会抛出异常(error) ERR index out of range
⑨Linsert:
Linsert将某一个具体的value插入到列表中的某个元素的前面或者后面
127.0.0.1:6379> Rpush mylist "hello"(integer) 1127.0.0.1:6379> Rpush mylist "world"(integer) 2127.0.0.1:6379> LINSERT mylist before "world" "other"(integer) 3127.0.0.1:6379> LRANGE mylist 0 -11) "hello"2) "other"3) "world"127.0.0.1:6379> LINSERT mylist after "world" "new"(integer) 4127.0.0.1:6379> LRANGE mylist 0 -11) "hello"2) "other"3) "world"4) "new"
redis中Set集合中的元素是不能重复的。
①sadd/smembers/sismember/scard
127.0.0.1:6379> sadd myset "hello"(integer) 1127.0.0.1:6379> sadd myset "fengye"(integer) 1127.0.0.1:6379> sadd myset "love fengye"(integer) 1127.0.0.1:6379> SMEMBERS myset #查看myset中所有的值1) "fengye"2) "love fengye"3) "hello"127.0.0.1:6379> SISMEMBER myset hello #判断某一个值是不是在set集合中(integer) 1127.0.0.1:6379> SISMEMBER myset world(integer) 0
127.0.0.1:6379> scard myset #获取set集合中内容元素的个数 (integer) 4
②srem
127.0.0.1:6379> SMEMBERS myset1) "fengye"2) "lovekuangshen2"3) "love fengye"4) "hello"127.0.0.1:6379> srem myset lovekuangshen2 #移除某一个元素(integer) 1127.0.0.1:6379> SMEMBERS myset1) "fengye"2) "love fengye"3) "hello"
③srandmember
127.0.0.1:6379> SRANDMEMBER myset"hello"127.0.0.1:6379> SRANDMEMBER myset"love fengye"127.0.0.1:6379> SRANDMEMBER myset"fengye"127.0.0.1:6379> SRANDMEMBER myset 2 #随机抽选出指定个数的元素1) "hello"2) "love fengye"
④spop
127.0.0.1:6379> spop myset #随机删除集合中的一些元素"fengye"127.0.0.1:6379> spop myset"love fengye"127.0.0.1:6379> SMEMBERS myset1) "hello"
⑤smove
127.0.0.1:6379> sadd myset "hello"(integer) 1127.0.0.1:6379> sadd myset "world"(integer) 1127.0.0.1:6379> sadd myset "fengye"(integer) 1127.0.0.1:6379> sadd myset2 "set2"(integer) 1127.0.0.1:6379> smove myset myset2 "fengye" #将指定的元素从一个set移动到另一个set集合中(integer) 1127.0.0.1:6379> SMEMBERS myset1) "world"2) "hello"127.0.0.1:6379> SMEMBERS myset21) "fengye"2) "set2"
⑥sdiff/sinter/sunion
127.0.0.1:6379> sadd key1 a(integer) 1127.0.0.1:6379> sadd key1 b(integer) 1127.0.0.1:6379> sadd key1 c(integer) 1127.0.0.1:6379> sadd key2 c(integer) 1127.0.0.1:6379> sadd key2 d(integer) 1127.0.0.1:6379> sadd key2 e(integer) 1127.0.0.1:6379> SDIFF key1 key2 # 差集1) "a"2) "b"127.0.0.1:6379> SINTER key1 key2 # 交集1) "c"127.0.0.1:6379> SUNION key1 key2 # 并集1) "a"2) "b"3) "c"4) "d"5) "e"
①hset/hget/hmget/hgetall:
127.0.0.1:6379> hset myhash field1 fengye # hset一个具体的key-value(integer) 1127.0.0.1:6379> hget myhash field1"fengye"127.0.0.1:6379> hmset myhash field1 hello field2 world #set多个key valueOK127.0.0.1:6379> hmget myhash field1 field2 #获取多个字段值1) "hello"2) "world"127.0.0.1:6379> hgetall myhash #获取全部的数据1) "field1"2) "hello"3) "field2"4) "world"#使用hash存取对象数据
127.0.0.1:6379> hmset myhash username zhangsan sex '男' age 24OK127.0.0.1:6379> HGETALL myhash 1) "field2" 2) "world" 3) "field1" 4) "hello" 5) "field3" 6) "5" 7) "filed3" 8) "1" 9) "field4"10) "hello"11) "username"12) "zhangsan"13) "sex"14) "\xe7\x94\xb7"15) "age"16) "24"
②hdel:
127.0.0.1:6379> hdel myhash field1 #删除hash中指定的key字段,对应的value值也就没有了(integer) 1127.0.0.1:6379> hgetall myhash1) "field2"2) "world"
③hlen:
127.0.0.1:6379> HGETALL myhash1) "field2"2) "world"3) "field1"4) "hello"127.0.0.1:6379> hlen myhash # 获取hash表的字段数量(integer) 2
④hexists:
127.0.0.1:6379> HEXISTS myhash field1 #判断hash中的key是否存在(integer) 1127.0.0.1:6379> HEXISTS myhash field3(integer) 0
⑤Hkeys/Hvals:
127.0.0.1:6379> HKEYS myhash # 查询所有的keys1) "field2"2) "field1"127.0.0.1:6379> HVALS myhash # 查询所有的vals1) "world"2) "hello"
⑥hincrby/hsetnx:
127.0.0.1:6379> hset myhash field3 5(integer) 1127.0.0.1:6379> HINCRBY myhash field3 1 #hash指定增量(integer) 6127.0.0.1:6379> HINCRBY myhash field3 -1 #hash自减(integer) 5127.0.0.1:6379> hsetnx myhash field4 hello #不存在则设置值(integer) 1127.0.0.1:6379> hsetnx myhash field4 world #存在则无法设置,分布式锁(integer) 0
①zadd/zrange:
127.0.0.1:6379> zadd myset 1 one #添加一个值(integer) 1127.0.0.1:6379> zadd myset 2 two 3 three #添加多个值(integer) 2127.0.0.1:6379> ZRANGE myset 0 -11) "one"2) "two"3) "three"
②zrangebyscore:
127.0.0.1:6379> clear127.0.0.1:6379> zadd salary 2500 xiaohong(integer) 1127.0.0.1:6379> zadd salary 4000 zhangsan(integer) 1127.0.0.1:6379> zadd salary 1000 fengye(integer) 1127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf #按照薪资高低升序排序1) "fengye"2) "xiaohong"3) "zhangsan"127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores #按照薪资高低升序排序,附带薪资1) "fengye" 2) "1000" 3) "xiaohong" 4) "2500" 5) "zhangsan" 6) "4000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores 1) "fengye" 2) "1000" 3) "xiaohong" 4) "2500"
③zrem:
127.0.0.1:6379> ZREM salary zhangsan #移除sorted set中指定的元素(integer) 1127.0.0.1:6379> ZRANGE salary 0 -11) "fengye"
④zcard:
127.0.0.1:6379> ZCARD salary #获取有序集合中元素的个数(integer) 2
⑤zrevrage:
127.0.0.1:6379> ZREVRANGE salary 0 -1 withscores #从大到小排列1) "xiaohong" 2) "2500"3) "fengye"4) "1000"
⑥zcount:
127.0.0.1:6379> zadd myset 1 hello(integer) 1127.0.0.1:6379> zadd myset 2 world 3 fengye(integer) 2127.0.0.1:6379> zcount myset 1 3 #获取指定区间的成员数量(integer) 3127.0.0.1:6379> zcount myset 1 2(integer) 2
Redis通过Geospatial可以根据地理位置如经度、纬度查询出两地之间的距离。主要分为以下几个命令:
①geoadd:
# 添加规则:除两极不能添加外,其它均能添加# 参数 key 经度 纬度 名称# 有效的经度从-180度到180度# 有效的纬度从-85.05112878度到85.05112878度
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing(integer) 1127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai # 添加地理位置(integer) 1127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen(integer) 2127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian(integer) 2
②geopos:
127.0.0.1:6379> geopos china:city beijing # 获取指定的成员的经度和纬度1) 1) "116.39999896287918091" 2) "39.90000009167092543"127.0.0.1:6379> geopos china:city beijing xian1) 1) "116.39999896287918091" 2) "39.90000009167092543"2) 1) "108.96000176668167114" 2) "34.25999964418929977"
③geodist:
计算两个城市地区之间的直线距离:
127.0.0.1:6379> geodist china:city beijing shanghai"1067378.7564"127.0.0.1:6379> geodist china:city beijing shanghai km # 查找北京到上海的直线距离,单位km"1067.3788"127.0.0.1:6379> geodist china:city beijing hangzhou km"1127.3378"
④georadius:
以给定的经纬度为中心,找出某一半径内的元素:
127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 1000 km #获取当前经度纬度下1000km以内的城市1) "chongqi"2) "xian"3) "shengzhen"4) "hangzhou"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km1) "chongqi"2) "xian"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withdist #获取该经度纬度下500km以内的城市并附带距离1) 1) "chongqi" 2) "383.1094"2) 1) "xian" 2) "449.8190"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withcoord #获取该经度纬度下500km以内的城市病显示城市的经度、纬度1) 1) "chongqi" 2) 1) "106.49999767541885376" 2) "29.52999957900659211"2) 1) "xian" 2) 1) "108.96000176668167114" 2) "34.25999964418929977"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withdist withcoord count 2 #count 2表示只显示2个1) 1) "chongqi" 2) "383.1094" 3) 1) "106.49999767541885376" 2) "29.52999957900659211"2) 1) "xian" 2) "449.8190" 3) 1) "108.96000176668167114" 2) "34.25999964418929977"
⑤georadiusbymember:
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km #以城市为中心查询出距离400km的城市1) "hangzhou"2) "shanghai"
⑥geohash:
该命令将返回11个字符的geohash字符串
127.0.0.1:6379> geohash china:city beijing chongqi1) "wx4fbxxfke0"2) "wm5xzrybty0"
⑦zset命令删除:
geo底层就是zset,所以我们可以使用zset进行删除:
127.0.0.1:6379> ZRANGE china:city 0 -11) "chongqi"2) "xian"3) "shengzhen"4) "hangzhou"5) "shanghai"6) "beijing"127.0.0.1:6379> ZREM china:city beijing(integer) 1
Redis基于hyperloglogs提供了一种更高效的算法来计算两个集合中的元素个数,重复个数不累计。
这种高效率的算法替代了传统使用set集合进行不重复元素的存取计算方式。
hyperloglogs的优点:
127.0.0.1:6379> PFADD mykey a b c d e f g h i j(integer) 1127.0.0.1:6379> PFCOUNT mykey(integer) 10127.0.0.1:6379> PFADD mykey2 i j z x c a b n m(integer) 1127.0.0.1:6379> PFCOUNT mykey2(integer) 9127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 #合并两个集合的元素OK127.0.0.1:6379> PFCOUNT mykey3 #计算元素的个数,不重复(integer) 14
注意:使用hyperloglogs有0.81%的错误率,如果不允许容错,需要精确计算的,则不能使用hyoerloglogs。
Bitmaps使用位0 1进行数据的存储。
适用场景:统计用户信息,活跃与非活跃、登录、打卡
使用Bitmaps来记录一周7天的打卡时间:
127.0.0.1:6379> setbit sign 0 1(integer) 0127.0.0.1:6379> setbit sign 1 0(integer) 0127.0.0.1:6379> setbit sign 2 0(integer) 0127.0.0.1:6379> setbit sign 3 1(integer) 0127.0.0.1:6379> setbit sign 4 1(integer) 0127.0.0.1:6379> setbit sign 5 0(integer) 0127.0.0.1:6379> setbit sign 6 0(integer) 0127.0.0.1:6379> getbit sign 3 #查看某一天是否有打卡(integer) 1127.0.0.1:6379> getbit sign 6(integer) 0
127.0.0.1:6379> BITCOUNT sign #统计打卡的天数 (integer) 3
原文链接:http://www.cnblogs.com/yif0118/p/14567893.html
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728