本文已参加「新人创作礼」活动, 一同敞开创作之路。
Redis 有 5 种根底数据结构,分别为:string (字符串)、list (列表)、set (调集)、hash (哈希) 和 zset (有序调集)。
一. string (字符串)
字符串 string 是 Redis 最简略的数据结构。Redis 一切的数据结构都是以仅有的 key 字符串作为名称,然后经过这个仅有 key 值来获取相应的 value 数据。不同类型的数据结构的差异就在于 value 的结构不一样。字符串结构运用十分广泛,一个常见的用处便是缓存用户信息。咱们将用户信息结构体运用 JSON 序列化成字符串,然后将序列化后的字符串塞进 Redis 来缓存。相同,取用户信息会经过一次反序列化的过程。
1. string的常用操作
(1) 键值对
# 存入字符串键值对
set key value
# 获取一个字符串键值对
get key
# 删去
del key
(2) 批量操作键值对
能够批量对多个字符串进行读写,节省网络耗时开销
# 批量存储字符串键值对
mset ket value [key value .....]
# 批量获取字符串键值对
mget key [key ......]
(3) 过期和 set 指令扩展
# 设置一个键(key)的过期时刻(seconds)
expire key seconds
# setex 等价于 set + expire
setex key seconds value
# 存入一个不存在的字符串键值对
setnx key value
(4) 原子操作
假设 value 值是一个整数,还能够对它进行自增操作。自增是有规模的,它的规模是 signed long 的最大最小值,超过了这个值,Redis 会报错
# 将 key 中存储的值加1
incr key
# 将 key 中存储的值减1
decr key
# 将 key 中存储的值加increment
incrby key increment
# 将 key 中存储的值减decrement
decrby key decrement
2. string的运用场景
Redis运用场景:惯例key-value缓存运用、惯例计数:微信大众号阅览次数,粉丝数等、分布式锁等
(1)单值缓存
set key value
get key
(2)目标缓存
set user:1 value(json格局数据)
mset user:1:name zhuge user:1:balance 1888
mget user:1:name user:1:balance
(3)计数器
incr article:readcount:{文章id}
get article:readcount:{文章id}
(4)分布式锁
(5)web集群session同享
这儿引荐王松大神的一篇文章:wangsong.blog.csdn.net/article/det…
(6)分布式体系全局序列号
redis批量生成序列号进步性能
二. hash (哈希)
String类型 存储的困惑
- 目标类数据的存储假设具有较为频频的更新需求,操作会显得笨重,存简单,改费事。
- 为了差异与Redis中的键值对的称号,hash中的键成为field,而key特指Redis的键。
hash类型
- 新的存储需求:对一系列存储的数据进行编组,方便办理,典型运用存储目标信息
- 需求的内存结构:一个存储空间保存多少个键值对数据
- hash类型:底层运用哈希表结构完成数据存储,相当于 Java 语言里面的 HashMap,它是无序字典。内部完成结构上同 Java 的HashMap 也是一起的,相同的数组 + 链表二维结构。第一维 hash 的数组方位磕碰时,就会将磕碰的元素运用链表串接起来。
1. hash的常用操作
(1)操作单个数据
# 增加修正数据
hset key field value
# 获取数据
hget key field
# 删去数据
hdel key field1 [field2 ...]
(2)操作多个数据
# 增加/修正多个数据
hmset key field1 value1 field2 calue2
#获取多个数据
hmget key field1 field2 …
# 获取哈希表key中field的数量
hlen key
# 获取哈希表key中一切的键值
hgetall key
# 获取哈希表中是否存在指定的字段
hexists key field
(3)原子操作
# 将 field 中存储的值加 increment
hincrby key field increment
# float 值
hincrbyfloat key field increment
2. hash的运用场景
(1)目标缓存
hmset user {userId}:name value {userId}:balance value
hmset user {1}:name zhuge {1}:balance 1888
(2)购物车
- 事务场景:电商网站购物车的设计与完成。
- 处理方案:
- 以客户id作为key,每位用户创立一个hash存储结构存储对应的购物车信息。
- 将产品编号作为field,购买数量作为value进行存储。
- 增加产品:追加全新的field与value。 hset cart:101 1001 1
- 阅读:遍历hash。 hgetall cart:101
- 更改数量:自增/自减,设置value值。 hincrby cart:101 1001 1
- 删去产品:删去field。 hdel cart:101 1001
- 清空:删去key。
3. hash的优缺陷
- 优点
- 同类数据归类整合贮存,方便数据办理。
- 比较string操作耗费内存与cpu更小。
- 比较string贮存更节省空间。
- 缺陷
- 过期功能不能运用在field上,只能用在key上。
- Redis集群架构下不适合大规模运用。
redis集群架构
三. List(列表)
- 数据存储需求:存储多个数据,并对数据进入存储空间的次序进行区分
- 需求的存储数据:一个存储空间保存多个数据,且经过数据能够体现进入次序
- list类型:保存多个数据,底层运用双向链表存储结构完成
1. list的常用操作
(1)增加/修正数据
# 将一个或多个值value刺进到key列表的表头(最左边)
lpush key value1 [value2 …]
# 将一个或多个值value刺进到key列表的表尾(最右边)
rpush key value1 [value2 …]
(2)获取并移除数据
# 移除并回来key列表的头元素
lpop key
# 移除并回来key列表的尾元素
rpop key
(3)获取数据
# 获取列表key中指定区间内的元素,从左数第start到stop个元素,从0开端
lrange key start stop
# 查询第i个元素
lindex key index
# list的长度
llen key
(4)规矩时刻内获取并移除数据
# 从key列表表头弹出一个元素,若列表中没有元素,堵塞等候timeout秒,假设timeout=0,一向堵塞等候
blpop key1 [key2 ...] timeout
# 从key列表表尾弹出一个元素,若列表中没有元素,堵塞等候timeout秒,假设timeout=0,一向堵塞等候
brpop key1 [key2 ...] timeout
开两个客户端,一个设置15s内获取list1中的值,此刻list1位空一向等候(堵塞),在15秒内另一个客户端存入到list1中数据,此刻就被获取到。
(5)移除指定数据
# 依据参数count的值,移除列表中与参数value相等的元素。count为移除的数量,value为移除哪个值
lrem key count value
2. 常用数据结构
- Stack(栈) = lpush + lpop → filo
- Queue(行列) = lpush + rpop
- Blocking MQ(堵塞行列) = lpush + brpop
3. list的运用场景
(1)最新音讯的展现
事务场景
-
新浪微博、twitter中个人用于的重视列表需求依照用户的重视次序进行展现,粉丝列表需求将最近重视的粉丝列在前面。
-
大众号、新闻、资讯类网站怎么将最新的新闻或资讯依照发生的事情次序展现。
-
企业运营过程中,体系将发生出很多的运营数据,怎么保障堕胎服务器操作日志的统一次序输出?
处理方案
- 依靠list的数据具有次序的特征对信息进行办理。
- 运用行列模型处理多路信息汇总合并的问题。
- 运用栈模型处理最新音讯的问题。
# 河北日报发了音讯,音讯id为1
lpush msg:user_id 1
# 央视网发了音讯,音讯id为2
lpush msg:user_id 2
# 检查最新大众号音讯
lrange msg:user_id 0 5
四. set(调集)
- 新的存储需求:存储很多的数据,在查询方面供给更高的效率
- 需求的存储结构:能够保存很多的数据,高效的内部存储机制,便于查询
- set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),而且值是不允许重复的。也便是只有键没有值的hash
1. set的常用操作
(1)增加数据
# 将一个或多个member元素参加到调集key傍边,现已存在于调集的member元素将被疏忽。若key不存在,则创立一个只包含member元素作成员的调集
sadd key member [member ...]
(2)获取数据
# 获取调集 key 中的一切成员
smembers key
# 获取调集key中元素的数量
scard key
# 判断调集key中是否存在member元素
sismember key member
# 获取调集key中的count个随机元素,并从调集key中移除
spop key [count]
# 获取调集key中的count个随机元素,不从调集key中移除
srandmember key [count]
(3)删去数据
# 移除调集 key 中的一个或多个 member 元素,不存在的 member 元素会被疏忽
srem key member [member ...]
2. set的运算操作
(1)交集
回来一个调集的悉数成员,该调集是一切给定调集的交集。 sinter key
代码示例:
redis> smembers group_1
1) "LI LEI"
2) "TOM"
3) "JACK"
redis> smembers group_2
1) "HAN MEIMEI"
2) "JACK"
redis> sinter group_1 group_2
1) "JACK"
将交集成果保存到destination调集,假设destination调集现已存在,则将其掩盖。destination能够是key本身。 sinterstore destination key [key …]
代码示例:
redis> smembers songs
1) "good bye joe"
2) "hello,peter"
redis> smembers my_songs
1) "good bye joe"
2) "falling"
redis> sintrestore song_interset songs my_songs
(integer) 1
redis> smembers song_interset
1) "good bye joe"
(2)并集
回来一个调集的悉数成员,该调集是一切给定调集的并集。 sunion key [key …]
代码示例:
redis> smembers songs
1) "Billie Jean"
redis> smembers my_songs
1) "Believe Me"
redis> sunion songs my_songs
1) "Billie Jean"
2) "Believe Me"
将并集成果保存到destination调集,假设destination调集现已存在,则将其掩盖。destination能够是key本身。 sunionstore destination key [key …]
代码示例:
redis> smembers NoSQL
1) "MongoDB"
2) "Redis"
redis> smembers SQL
1) "sqlite"
2) "MySQL"
redis> sunionstore db NoSQL SQL
(integer) 4
redis> smembers db
1) "MySQL"
2) "sqlite"
3) "MongoDB"
4) "Redis"
(3)差集
回来一个调集的悉数成员,该调集是一切给定调集之间的差集。 sdiff key [key …]
代码示例:
redis> smembers peters_movies
1) "bet man"
2) "start war"
3) "2012"
redis> smembers joes_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"
redis> sdiff peters_movies joes_movies
1) "bet man"
2) "start war"
将差集成果保存到destination调集,假设destination调集现已存在,则将其掩盖。destination能够是key本身。 sdiffstore destination key [key …]
代码示例:
redis> smembers joes_movies
1) "hi, lady"
2) "Fast Five"
3) "2012"
redis> smembers peters_movies
1) "bet man"
2) "start war"
3) "2012"
redis> sdiffstore joe_diff_peter joes_movies peters_movies
(integer) 2
redis> smembers joe_diff_peter
1) "hi, lady"
2) "Fast Five"
3. set的运用场景
(1)微信抽奖小程序
- 点击参加抽奖参加set调集
sadd key {user_id}
- 检查参加抽奖一切用户
smembers key
- 抽取count名中奖者
srandmember key [count] / spop key [count]
(2)随机引荐
redis运用于随机引荐类信息检索,例如热门歌单引荐,热门新闻引荐,热门旅行线路,运用APP引荐,大V引荐等。
事务场景:
每位用户初次运用进入头条时候会设置3项爱好的内容,可是后期为了增加用户的活跃度,爱好点,有必要让用户对其他信息类别逐渐发生爱好,增加客户留存度,怎么完成?
事务剖析:
- 体系剖析出各个分类的最新或最热门信息条目并组织成set调集
- 随机挑选其间部分信息
- 合作用户重视信息分类中的热门信息组织展现的全信息调集
处理方案:
- 随机获取调集中指定数量的数据
srandmember key [count]
- 随机获取调集中的某个数据并将该数据移出调集
spop key
(3)一起老友
- 脉脉为了促进用户间的交流,保障事务成单率的进步,需求让每位用户拥有很多的老友,事实上职场新人不具有更多的职场老友,怎么快速为用户堆集更多的老友?
- 新浪微博为了增加用户热度,进步用户留存性,需求微博用户在重视更多的人,以此取得更多的信息或热门话题,怎么进步用户重视别人的总量?
- QQ新用户入网年纪越来越低,这些用户的朋友圈交际圈十分小,往往集中在一所校园乃至一个班级中,怎么协助用户快速堆集老友用户带来更多的活跃度?
- 微信大众号是微信信息流通的渠道之一,增加用户重视的大众号成为进步用户活跃度的一种方法,怎么协助用户堆集更多重视的大众号?
- 美团外卖为了进步成单量,有必要协助用户挖掘美食需求,怎么引荐给用户最适合自己的美食? 处理方案:
# 我重视的人
redis> smembers mySet
1) "zhuge"
2) "yangguo"
3) "sima"
# 杨过重视的人
redis> smembers yangguoSet
1) "zhuge"
2) "sima"
3) "luban"
4) "guojia"
# 司马重视的人
redis> smembers simaSet
1) "zhuge"
2) "yangguo"
3) "guojia"
4) "luban"
5) "xunyu"
- 一起重视
# 我和杨过一起重视
redis> sinter yangguoSet mySet
1) "zhuge"
2) "sima"
- 我重视的人也重视他
# 我重视的人也重视杨过
redis> sismember simaSet yangguo
(integer) 1
- 我或许知道的人
redis> sdiff mySet yangguoSet
1) "luban"
2) "guojia"
(4)拜访量核算去重
公司对旗下新的网站做推广,核算网站的PV (拜访量),UV (独立访客),IP (独立IP)。
- PV:网站被拜访次数,可经过刷新页面进步拜访量。
- UV:网站被不同用户拜访的次数,可经过cookie核算拜访量,相同用户切换IP地址,UV不变。
- IP:网站被不同IP地址拜访的总次数,可经过IP地址核算拜访量,相同IP不同用户拜访,IP不变。
处理方案:
针对不同的核算类型有不同的数据存储方法:
- 使用set调集的数据去重特征,记载各种拜访数据
- 树立string类型数据,使用incr核算日拜访量(PV)
- 树立set模型,记载不同cookie数量(UV)
- 树立set模型,记载不用IP数量(IP)
(5)是非名单
黑名单:
资讯类信息类网站寻求高拜访量,可是因为其信息的价值,往往简单被不法分子使用,经过爬虫技能,快速获取信息,个别特种行业网站信息经过爬虫获取剖析后,能够转换成商业秘要进行出售。例如第三方火车票、机票、酒店刷票代购软件、电商刷谈论、刷好评。 同时爬虫带来的伪流量也会给运营者带来错觉,发生过错的决议计划,有用防止网站被爬虫反复爬取成为每个网站都要考虑的基本问题。在依据技能层面区分出爬虫用户后,需求将此类用户进行有用的屏蔽,这便是黑名单的典型运用。 ps:不是说爬虫一定做摧毁性的作业,有些小型网站需求爬虫为其带来一些流量。
白名单:
关于安全性更高的运用拜访,仅仅靠黑名单是不能处理安全问题的,此刻需求设定可拜访的用户集体,依靠白名单做更为严苛的拜访验证。
处理方案:
- 依据运营战略设定问题用户发现、辨别规矩
- 周期性更新满意规矩的用户黑名单,参加set调集
- 用户行为信息到达后与黑名单进行比对,承认行为去向
- 黑名单过滤IP地址:运用于开放游客拜访权限的信息源
- 黑名单过滤设备信息:运用于限制拜访设备的信息源
- 黑名单过滤用户:运用于依据拜访权限的信息源
五. sorted_set(有序调集)
- 新的存储需求:依据排序有利于数据的有用显现,需求供给一种能够依据本身特征进行排序的方法。
- 需求的存储结构:新的存储模型,能够保存可排序的数据。
- zset类型:在set的存储结构根底上增加可排序字段。
1. sorted_set的常用操作
(1)增加数据
# 将一个或多个 member 元素及其 score 值参加到有序集 key 傍边。
zadd key score member [[score member] [score member] …]
- 假设某个 member 现已是有序集的成员,那么更新这个 member 的 score 值,并经过从头刺进这个 member元素,来保证该 member 在正确的方位上。
- score 值能够是整数值或双精度浮点数。
- 假设 key 不存在,则创立一个空的有序集并履行 ZADD 操作。
- 当 key 存在但不是有序集类型时,回来一个过错。
(2)获取数据
# 获取有序集 key 中,成员 member 的 score 值
zscore key member
# 获取有序集 key 的成员的数量。
zcard key
# 获取有序集 key 中, score 值在 min 和 max 之间(默许包含 score 值等于 min 或 max )的成员的数量。
zcount key min max
# 正序(从小到大)获取有序集 key 中,指定区间内[start到stop]的成员。
zrange key start stop [WITHSCORES]
# 倒序(从大到小)获取有序集 key 中,指定区间内[start到stop]的成员。
zrevrange key start stop [WITHSCORES]
- 下标参数 start 和 stop 都以 0 为底,也便是说,以 0 表明有序集第一个成员,以 1 表明有序集第二个成员,以此类推。你也能够运用负数下标,以 -1 表明最后一个成员, -2 表明倒数第二个成员,以此类推。
- 超出规模的下标并不会引起过错。 比如说,当 start 的值比有序集的最大下标还要大,或是 start > stop 时, zrange指令只是简略地回来一个空列表。 另一方面,假设 stop 参数的值比有序集的最大下标还要大,那么 Redis 将 stop 当作最大下标来处理。
(3)删去数据
# 移除有序集 key 中的一个或多个成员,不存在的成员将被疏忽。
zrem key member [member …]
- 条件删去
# 移除有序集 key 中,指定排名(rank)区间内的一切成员。
zremrangebyrank key start stop
# 移除有序集 key 中,一切 score 值介于 min 和 max 之间(包含等于 min 或 max )的成员。
zremrangebyscore key min max
示例:
redis> ZADD salary 2000 jack
(integer) 1
redis> ZADD salary 5000 tom
(integer) 1
redis> ZADD salary 3500 peter
(integer) 1
redis> ZREMRANGEBYRANK salary 0 1 # 移除下标 0 至 1 区间内的成员
(integer) 2
redis> ZRANGE salary 0 -1 WITHSCORES # 有序集只剩下一个成员
1) "tom"
2) "5000"
redis> ZRANGE salary 0 -1 WITHSCORES # 显现有序集内一切成员及其 score 值
1) "tom"
2) "2000"
3) "peter"
4) "3500"
5) "jack"
6) "5000"
redis> ZREMRANGEBYSCORE salary 1500 3500 # 移除一切薪水在 1500 到 3500 内的职工
(integer) 2
redis> ZRANGE salary 0 -1 WITHSCORES # 剩下的有序集成员
1) "jack"
2) "5000"
(4)原子操作
# 为有序集 key 的成员 member 的 score 值加上增量 increment 。
zincrby key increment member
示例:
redis> ZSCORE salary tom
"2000"
redis> ZINCRBY salary 2000 tom # tom 加薪啦!
"4000"
2. sorted_set调集操作
(1)并集
# 核算给定的一个或多个有序集的并集,其间给定 key 的数量有必要以 numkeys 参数指定,并将该并集(成果集)贮存到 destination 。
zunionstore destination numkeys key [key …]
示例:
redis> ZRANGE programmer 0 -1 WITHSCORES
1) "peter"
2) "2000"
3) "jack"
4) "3500"
5) "tom"
6) "5000"
redis> ZRANGE manager 0 -1 WITHSCORES
1) "herry"
2) "2000"
3) "mary"
4) "3500"
5) "bob"
6) "4000"
redis> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 # 公司决议加薪。。。除了程序员。。。
(integer) 6
redis> ZRANGE salary 0 -1 WITHSCORES
1) "peter"
2) "2000"
3) "jack"
4) "3500"
5) "tom"
6) "5000"
7) "herry"
8) "6000"
9) "mary"
10) "10500"
11) "bob"
12) "12000"
(2)交集
# 核算给定的一个或多个有序集的交集,其间给定 key 的数量有必要以 numkeys 参数指定,并将该交集(成果集)贮存到 destination 。
zinterstore destination numkeys key [key …]
示例:
redis > ZADD mid_test 70 "Li Lei"
(integer) 1
redis > ZADD mid_test 70 "Han Meimei"
(integer) 1
redis > ZADD mid_test 99.5 "Tom"
(integer) 1
redis > ZADD fin_test 88 "Li Lei"
(integer) 1
redis > ZADD fin_test 75 "Han Meimei"
(integer) 1
redis > ZADD fin_test 99.5 "Tom"
(integer) 1
redis > ZINTERSTORE sum_point 2 mid_test fin_test
(integer) 3
redis > ZRANGE sum_point 0 -1 WITHSCORES # 显现有序集内一切成员及其 score 值
1) "Han Meimei"
2) "145"
3) "Li Lei"
4) "158"
5) "Tom"
6) "199"
3. sorted_set运用场景
(1)排行榜
处理方案:
- 点击新闻,点击量 +1
zincrby hotNews:20210104 1 特朗普通话语音曝光
- 展现当日排行前十
zrevrange hotNews:20210104 0 9 WITHSCORES
- 七日搜索榜单核算
zunionstore hotNews:20210104-2021010110 7 hotNews:20210104 hotNews:20210105 ... hotNews:20210110
- 展现七日排行前十
zrevrange hotNews:20210104-2021010110 0 9 WITHSCORES
(2)会员短期体会之过期失效
根底服务+增值服务类网站会设定各位会员的试用,让用户充分体会会员优势。例如观影试用VIP、游戏VIP体会、云盘下载体会VIP、数据检查体会VIP,当VIP体会到期后,怎么有用办理此类信息。即便关于正式VIP用户也存在对应的办理方法。 网站会定期敞开投票、评论,限时进行,逾期作废。怎么有用办理此类过期信息。
处理方案:
- 关于依据时刻线限制的使命处理,将处理时刻记载为score值,使用排序功能区分处理的先后次序
- 记载下一个要处理的事情,当比照体系时刻发现当然仍后到期后移除redis中的记载,并记载下一个要处理的时刻
- 当新使命参加时,断定并更新当前下一个要处理的使命时刻
- 为进步sorted_set的性能,通常将使命依据特征存储成若干个sorted_set.例如1小时内,1天内,年度等,操作时逐渐进步,将行将操作的若干个使命归入到1小时内处理行列中
- time指令获取当前体系时刻
如有问题或技能交流➕微:JavaBoy_1024