redis常用5种数据类型包括:string、hash、list、set、zset。如图:
不常用的3种数据类型有:BitMap(2.2版新加)、Geo(3.2版新加)、HyperLogLog(2.8版新加)。
目录
3、关注模型(包括我关注的人,共同关注、我关注的人也关注她、我可能认识的人)
一、字符串string
(1)常用操作命令:
字符串常用操作:
- SET key value //存入字符串键值对
- MSET key value[key value……] //批量存储字符串键值对
- SETNX key value //存入一个不存在的键值对(分布式锁常用命令)
- GET key //获取一个字符串键值
- MGET key[key……] //批量获取字符串键值
- DEL key[key……] //删除一个键
- EXPIRE key seconds //设置一个键的过期时间(秒)
- GETRANGE key start stop //字符串截取操作,索引下标从start到stop
原子加减操作:
- INCR key //将key中存储的数字值加1
- DECR key //将key中存储的数字值减1
- INCRBY key increment //将key中所存储的值加上increment
- DECRBY key increment //将key中所存储的值减去increment
(2)应用场景
1、单值缓存:
使用SET key value缓存值,使用GET key获取值,使用DEL key删除值即可。
2、对象缓存:
两种方式:缓存对象json值或是把值拆开保存。
- 设置值:SET user:1 value(json数据格式) 获取值:GET user:1
- 设置值:MSET user:1:name zhangsan user:1:money 1000 获取值:MSET user:1:name user:1:money
可以比较两种方式发现,
第一种json方式我们常用,便于理解,但是修改效率不高。
第二种方式,操作复杂,但是如果需要单独获取或修改某个值效率较高。因为第一种方式需要先json反序列化,修改完成再序列化这些复杂的操作。
同时这种方式只需要取出某一个字段修改保存即可,不需要全部取出来。
3、分布式锁:
执行SETNX product:1 true命令加锁 ///返回1代表获取锁成功,返回0代表失败,前端可以提示“系统繁忙,请稍后再试!”
执行SET product:1 true ex 10 nx //防止死锁,需要加上超时时间
执行完业务操作,执行DEL product:1清除锁(此代码放在try-finall块中)
注意:上面命令在加锁完成之后,设置超时时间之前,如果系统挂掉了依然会导致死锁。
所以需要加锁和设置超时时间合并为一条命令(原子操作),具体需要上网查一下
4、计数器:
例如:可以用来记录某文章访问人数
INCR article:readcount:{文章ID} //自增计数,返回自增后的值。如果原来没有值,则返回1
GET article:readcount:{文章ID}
5、web集群session共享
可以使用spring session +redis实现session共享,命令和上面对象缓存一样
6、分布式系统全局序列号生成
INCRBY orderId 1000 //redis批量生成序列化提升性能
二、哈希hash
优点:
- 同类数据归类整合存储,方便数据管理
- 比string操作消耗内存与cpu更小
- 比string存储更节省空间
缺点:
- 过期时间不能用在field上,只能用在key上
(1)常用操作命令
- HSET key field value //存储一个哈希表key的键值
- HSETNX key field value //存储一个不存在的哈希表key的键值
- HMSET key field value[field value……] //在一个哈希表key中存储多个键值对
- HGET key field //获取哈希表key对应的field键值
- HMGET key field[field……] //批量获取哈希表key中多个field键值
- HDEL key field[field…… ] //删除哈希表key中的field键值
- HLEN key //返回哈希表key中field的数量
- HGETALL key //返回哈希表key中所有的键值
- HINCRBY key field increment //为哈希表key中field键的值加上增量increment
(2)应用场景
1、对象缓存
拿string中的对象缓存来举例
HMSET user 1:name zhangsan 1:money 1000 //以user为key。id+name为field保存
HMGET user 1:name 1:money //获取
2、电商购物车
例如:以上是京东购物车页面,可以用redis来实现。(假设用户id是202 商品ID是5005)
首先我们可以以用户的id为hash中的key,商品id为field,商品数量为value。
当我们对购物车进行操作时:
- 添加商品:HSET car:202 5005 1 (存储一个哈希表key的键值)
- 增加商品数量:HINCRBY car:202 5005 1 (为哈希表key中field键的值加上增量increment)
- 获取商品总数:HLEN car:202 (返回哈希表key中field的数量)
- 删除商品:HDEL car:202 5005 (删除哈希表key中的field键值)
- 获取购物车所有商品:HGETALL car:202 (返回哈希表key中所有的键值)
上面的操作一句命令就搞定了,比起mysql,简单高效,还不用担心并发问题。
三、列表list
(1)常用操作命令
- LPUSH key value[value……] //将一个或多个值value插入到key列表的表头(最左边)
- RPUSH key value[value……] //将一个或多个值value插入到key列表的表尾(最右边)
- LPOP key //移除并返回key列表的头元素
- RPOP key //移除并返回key列表的尾元素
- LRANGE key start stop //返回列表key中指定区间内的元素,区间偏移量由start和stop指定
- BLPOP key[key……] timeout //从key列表表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0则一直等待
- BRPOP key[key……] timeout //从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0则一直等待
由于list命令的多样性,所以list可以实现三种数据类型:
- LPUSH+LPOP命令组成栈(先入后出,头入头出)
- LPUSH+RPOP命令组成队列(先入先出,头入尾出)
- LPUSH+BRPOP命令组成阻塞队列(先入先出,头入尾阻塞出)
(2)应用场景
1、用作队列
LPUSH放数据。RPOP取数据。
2、用作消息队列mq
提供者:使用LPUSH往队列中放数据
消费者:使用BRPOP往队列中取数据,如果没数据会阻塞。
3、微信订阅号消息
如果我关注了“备胎说车”公众号,那么它发消息(id:5005)我会收到,这个功能用redis来实现。
1)针对每个用户(id:202)创建一个队列 ,关注的公众号发消息则直接把消息id放入list队列:
LPUSH msg:202 5005(将一个或多个值value插入到key列表的表头)
2)查看最新的消息(前5条):
LRANGE msg:202 0 4 (返回列表key中指定区间内的元素,下标从0开始)
四、集合set
(1)常用操作命令
set常用操作:
- SADD key member[member……] //往集合key中存入元素,元素存在则忽略
- SREM key member[member……] //从集合key中删除元素
- SMEMBERS key //获取集合key中所有的元素
- SCARD key //获取集合key中元素的个数
- SISMEMBER key member //判断member元素是否存在于集合key中
- SRANDMEMBER key [count] //从集合key中选出count个元素,元素不从key中删除
- SPOP key [count] //从集合key中选出count个元素,元素从key中删除
set运算操作:
- SINTER key[key……] //交集运算
- SINTERSTORE destination key [key] //将交集的结果存入新集合destination中
- SUNION key[key……] //并集运算
- SUNIONSTORE destination key [key] //将并集的结果存入新集合destination中
- SDIFF key[key……] //差集运算
- SDIFFSTORE destination key [key] //将差集的结果存入新集合destination中
(2)应用场景
1、抽奖功能
抽奖的功能可以用redis的set集合来实现。方法:
1)点击参与抽奖加入集合
SADD choujiang {userId} (往集合choujiang中存入元素)
2)查看参与抽奖的所有用户
SMEMBERS choujiang (获取集合choujiang中所有的元素)
3)抽取1人中奖者
SRANDMEMBER choujiang 1 (从集合choujiang中选出count个元素,元素不从choujiang中删除)
4)抽取等级中奖者(一二三等奖):
- 三等奖(3人):SPOP choujiang 3 (从集合choujiang中选出count个元素,元素从choujiang中删除)(关键是需要剔中奖的人)
- 二等奖(2人):SPOP choujiang 2
- 二等奖(1人):SPOP choujiang 1
2、点赞、收藏、标签等功能
例如:微信的点赞功能,使用redis set集合实现。方法:
1)点赞
SADD like:{消息id} {用户id} (往集合中存入元素)
2)取消点赞
SREM like:{消息id} {用户id} (从集合key中删除元素)
3)检查用户是否点过赞
SISMEMBER like:{消息id} {用户id} (判断元素是否存在于集合中)
4)获取点赞的用户列表
SMEMBERS like:{消息id} (获取集合中所有的元素)
5)获取点赞用户数
SCARD like:{消息id} (获取集合中元素的个数)
3、关注模型(包括我关注的人,共同关注、我关注的人也关注她、我可能认识的人)
例如:微博的微关系模块
假设:
我关注的人是:meSet -->{zhangsan,lisi,wangwu}
张三关注的人是:zhangsanSet -->{me,lisi,wangwu,zhaoliu}
李四关注的人是:lisiSet -->{me,zhangsan,zhoaliu,wangwu,zhouqi}
1)我和张三共同关注的人(取交集)
SINTER meSet zhangsanSet -->{lisi,wangwu} (交集运算)
2)我关注的人也关注他(张三)
SISMEMBER lisiSet zhangsan (判断李四关注集合中是否有张三)
SISMEMBER wangwuSet zhangsan (判断王五关注集合中是否有张三)
把我关注的人(除张三外)全部判断一遍即可
3)我可能认识的人(取差集)
SDIFF zhangsanSet meSet -->{me,zhaoliu} (差集运算)
把我关注的人全部取差集判断一遍即可
4、推荐功能
例如:推荐好文章一类的功能。和上面(我可能认识的人)类似。使用差集取得好友查看过的文章或点赞过的文章
五、有序集合zset(和set类似,只是增加了排序)
(1)常用操作命令
- ZADD key score member[score member……] //往集合key中存入元素,按照score来升序排序
- ZREM key member //从集合key中删除元素
- ZCARD key //返回集合key中元素的数量
- ZINCRBY key increment member //将指定key集合中member元素的值递增increment
- ZCOUNT key min max //返回key对应有序集合中,分值在min~max之间元素的数量
- ZRANK key member //返回指定key对应有序集合中,指定元素member在集合中的排名,从小到大升序。
- ZSCORE key member //返回key对应有序集合中,指定元素member对应的score分值
- ZRANGE key min max [withscores] //返回指定key对应的有序集合中,索引的min~max之间的元素信息,如果有withscores属性,把分值也带出来。
- ZREVRANK key //返回指定key对应的集合中,指定member在其中的排名,注意排名从0开始且按照分值从大到小降序
- zrevrange key start end [withscores] //指定key对应的集合中,分值在 start~end之间的降序,加上 withscores 的话可以将分值以及value都显示出来
- zrangebyscore key start end [withscores] //同 zrange命令不同的是,zrange命令是索引在startend范围的查询,而zrangebyscore命令是根据分值在startend之间的查询且升序展示
- zrevrangebyscore key max min [withscores] //同zrangebyscore命令不同的是,zrangebyscores是根据分值从小到大升序展示,而zrevrangebyscore命令是从max到min降序展示
- zremrangebyrank key start end //移除指定key对应集合中索引在start~end之间(包括start和end本身)的元素
- zremrangebyscore by min max //同zremrangebyrank命令类似,不同的该命令是删除分值在min~max之间的元素
- zinterstore desk-key key-count key... //获取指定数量的key的交集。例如有 key1:{10:A,20:B,30:C},key2{40:B,50:C,60:D},那么命令 zinterstore key3 2 key1 key2 意思就是 将key1 key2这两个集合的交集 赋给key3,如何获取key1与key2的交集呢。 key1中存在 A B C,key2中存在 B C D,那么交集就是 B 和 C,且 B与C对应的score也会叠加,即 key3{B:20+40=60,C:30+50=80}
- zunionstore desk-key key-count key... //获取指定数量key的并集,例如有 key1{10:A,20:B,30:C},key2{40:B,50:C,60:D},可以看出 A和D不是key1与key2共有的,但是并集中只要存在就会记录进去,然后B与C是共有的,即 并集的结果就是 key3{10:A,B:60,D:60,C:80}
(2)使用场景
-
根据时间排序的新闻列表等
- 排行榜等
六、BitMap(位图)
通过一个bit位来表示某个元素对应的值或状态
(1)常用操作命令
- SETBIT key offset value //设置key偏移量为offset(只能数字)的bit位的值(只能0或1)
- GETBIT key offset //获取key偏移量为offset的bit位的值
- BITCOUNT key [start stop] //获取key指定范围(start end)内的bit位的值为1的个数
- BITOP op destkey key key2[key3……] //对多个key进行运算(op可以是and交集、or并集、not非集、xor异或)将结果返回在destkey中
- BITPOS key targetBit [start end] //查找第一个值为targetBit(0或1)的位置(索引下标)
(2)应用场景
1、用户签到
签到:SETBIT signin:2020-01-24 用户id 1 //设置bit位为1
查询是否签到:SETBIT signin:2020-01-24 用户id //如果为1则说明已签到
2、统计活跃用户
用户上线:SETBIT loginon:2020-01-24 用户id 1 //设置bit位为1
统计活跃用户:BITCOUNT loginon:2020-01-24 查询所有上过线的用户总数
统计连续5天上线用户:BITOP and continu5day loginon:2020-01-24 loginon:2020-01-25…… (五天的登录记录取交集)
3、用户在线状态
查询在线状态:GETBIT online:2020-01-24 用户id //如果为1则说明在线
4、是否……(做过什么操作,可以用0或1表示的功能都行)
是否为会员、是否参加过某次活动、是否已读某篇文章等等……
七、Geo(位置集合)
用于存储地理位置信息,并对信息进行操作。
(1)常用操作命令
- GEOADD key longitude latitude member [longitude latitude member……] //添加地理位置的坐标 (经度longitude、纬度latitude、位置名称member)
- GEOPOS key member //从key中获取指定名称的地理位置(经度和纬度)
- GEODIST key member member2 [m|km|ft|mi] //计算并返回两个位置之间的距离。m:米(默认)、km千米、ft英尺、mi英里
- GEORADIUS key longitude latitude redius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] //根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。WITHDIST:将位置元素和中心的距离也返回。WITHCOORD:将位置元素的经纬度也返回。COUNT:限制返回的数量。asc:由近及远排序,desc相反。
- GEORADIUSBYMEMBER key member redius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] //根据存储在位置集合里面的某个地点获取指定范围内的地理位置集合
- GEOHASH key member [member……] //返回一个或多个位置对象的geohash的值
(2)应用场景
适合精度不高的场景:找附近的房、找附近的商铺、找附近的人等功能适合Geo。
精度高的场景:打车等功能适合用Google S2。
1、附近的人
保存坐标:GEOADD……
获取附近的人:GEORADIUS或GEORADIUSBYMEMBER 命令
八、HyperLogLog
进行基数统计用,存在一定误差,但是占用内存非常少。(个人感觉和set集合很类似)
注意:只能统计数量,不能获取元素内容
基数是指在一批数据中不重复的元素有多少。{1,2,3,3,4}-->{1,2,3,4}
(1)常用操作命令
- PFADD key value[value1 value2……] //向HyperLogLog中添加元素(如果key不存在会创建一个空的HyperLogLog结构)
- PFCOUNT key //获取Hyperloglog的近似基数。获取指后会被缓存,直到下一次PFADD命令执行
- PFMERGE destkey key key2[key3……] //将多个key合并为destkey
(2)应用场景
1、注册IP数、每日访问Ip数、页面实时UV、在线用户数等
接口被请求时,把ip放入:PFADD ip 192.168.1.100
统计访问的人数(ip数):PFCOUNT ip