1 Redis概述
1-1 redis的背景知识
redis常常出现在海量用户以及高并发的场景下,传统的关系型数据库存在的问题:
1)性能瓶颈:磁盘IO性能低下
- 降低磁盘IO次数,越低越好(放入内存)
2)扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群
- 去除数据间关系,越简单越好(不存储关系,仅存储数据)
非关系数据库的定义:Not-Only SQL( 泛指非关系型的数据库),作为关系型数据库的补充
NoSQL的特点
1)可扩容,可伸缩
2)大数据量下高性能
3)灵活的数据模型
4)高可用
常见的NoSQL数据库
Redis
memcache
HBase
MongoDB
1-2 NoSQL在实际场景中的位置(电商为例)
信息特点 | 对应工具 |
---|---|
商品基本信息(名称,价格,厂商) | MySQL |
商品附加信息(描述,详情,评论) | MongDB |
图片信息 | 分布式文件系统 |
搜索关键字 | ES、 Lucene、 solr |
热点信息 | Redis、 memcache、 tair |
总结:MySQL服务器存储基础信息并联通在一起向上层提供服务,上层将基础数据进行整合划分,比如文档(mongoDB),
图片(FastDFS),搜索关键字(ES),热点信息(redis)等。
1-3 Redis定义与特点
概念: Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对( key-value)数据库。
特征:
1.数据间没有必然的关联关系
2. 内部采用单线程机制进行工作
3. 高性能。官方提供测试数据, 50个并发执行100000 个请求,读的速度是110000 次/s,写的速度是81000次/s。
4. 多数据类型支持(5种)
字符串类型 string
列表类型 list
散列类型 hash
集合类型 set
有序集合类型 sorted_set
5.持久化支持。可以进行数据灾难恢复
1-4 Redis的应用场景
1)为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等
2)任务队列,如秒杀、抢购、购票排队等
3)即时信息查询,如各位排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设
备信号等
4)时效性信息控制,如验证码控制、投票控制等
5)分布式数据共享,如分布式集群架构中的 session 分离
6)消息队列
7)分布式锁
1-5 简单的使用介绍
启动界面:如下图所示,每个Redis程序实例会被分配Port和PID。
服务端:
[8280] 03 May 23:21:49.440 # Warning: no config file specified, using the default config. In order to specify a config file use C:UsersAdministratorDesktopRedis-x64-3.2.100
edis-server.exe /path/to/redis.conf
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.100 (00000000/0) 64 bit
.-`` .-```. ```/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 8280
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
[8280] 03 May 23:21:49.452 # Server started, Redis version 3.2.100
[8280] 03 May 23:21:49.453 * The server is now ready to accept connections on port 6379
客户端启动(命令行界面):
127.0.0.1:6379>
基本操作命令
set key value // 设置key对应的value
get key // 获取key对应的value
clear // 清除屏幕信息
quit/exit/<ESC> // 退出
2 Redis数据类型基础知识
2-1 数据类型概述(重要)
数据类型 | 特点 | 存储数据类型 | 应用场景 |
---|---|---|---|
string | 最基本的类型 | string | 数值型的字符串的使用:1)用于解决数据分表的主键重复问题。 2)用于设置数据的生命周期。 |
hash | 适合用于存储对象 | 只能存储字符串,不允许嵌套 | 用于实现购物车数据的存储,加快数据的呈现。 |
list | 底层是双向链表 | 保存数据是string | 1)具有操作顺序先后的数据的控制(朋友圈点赞用户显示)2)最新消息展示(关注顺序,日志信息按照时间显示) |
set | 可以看成只有key的hash | string | 1)随机推荐类信息检索(信息推荐) 2)信息的检索(共同好友)3)统计网站PV,UV,IP(去重) 4)黑白名单的维护 |
sortedset | 有序的set集合,相比较set加入score进行排序 | 1)排行榜数据的显示。2)定时任务的顺序执行(VIP会员到期)3)带有权重的信息处理次序 |
String
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。常规key-value缓存应用;常规计数:微博数,粉丝数等。
Hash
Hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,后续操作的时候,你可以直接仅 仅修改这个对象中的某个字段的值。比如我们可以Hash数据结构来存储用户信息,商品信息等。
List
list 就是链表,Redis list 的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表, 消息列表等功能都可以用Redis的 list 结构来实现。
Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
另外可以通过 lrange 命令,就是从某个元素开始读取多少个元素,可以基于 list 实现分页查询,这个很棒的一个功 能,基于 Redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西(一页一页的往下走),性能高。
Set
set 对外提供的功能与list类似是一个列表的功能,特殊之处在于 set 是可以自动排重的。
当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在 一个set集合内的重要接口,这个也是list所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。
比如:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常 方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程,具体命令如下:sinterstore key1 key2 key3
将交集存在key1内。
Sorted Set
和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。
举例:在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维 度的消息排行榜)等信息,适合使用 Redis 中的 SortedSet 结构进行存储。
redis相关联系的常见的业务数据:
- 缓存数据
原始业务功能设计
秒杀
618活动
双11活动
排队购票
2. 运营平台监控到的突发高频访问数据
突发时政要闻,被强势关注围观
3. 高频、复杂的统计数据
在线人数
投票排行榜
- 附加功能
系统功能优化或升级
单服务器升级集群
Session 管理
Token 管理
redis数据存储格式
redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储
- key只有字符串类型
- 数据类型通常指的是value的类型!!!!!!!!
2-2 String类型数据
String是最简单的数据存储类型,也是最常用的数据存储类型 。
相关的操作命令
/*单条数据的设置,获取,删除*/
set key value
get key
del key
/*多条数据的设置与获取*/
mset key1 value1 key2 value2 …
mget key1 key2 …
strlen key
append key value
2-2-1 问题:单条数据操作与多条数据操作的区别?
具体的指令的使用需要结合实际场景与数据规模进行确定,多条指令的优势在于发送与获取数据的过程只需要进行一次。通常情况下使用多条指令语句获取适合大小的批量数据。
- 如果有一个亿条数据,我们不能采用一条命令获取,仍然需要进行切割。
- Redis采用单线程处理,如果某个操作时间较长,会影响其他操作,所以redis单个操作时间复杂度不能太高。
2-2-2 Redis中String类型应用1:解决数据分表主键重复问题
业务场景:大型企业级应用中,分表操作是基本操作,使用多张表存储同类型数据,但是对应的主键 id 必须保证统一性,不能重复。 Oracle 数据库具有 sequence 设定,可以解决该问题,但是 MySQL数据库并不具有类似的机制,如何解决分表操作时的可能出现的主键重复问题?
Redis的解决策略?
基本思路:分表时为每个数据表指定主键自增策略,策略在设计的时候避免主键id的重复。可以将 redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性,此方案适用于所有数据库,且支持数据库集群
具体实现:redist提供了数值型的String的增减与减少命令。
相关命令
- 实现String类型数据增减指定数值
incr key
incrby key increment
incrbyfloat key increment
decr key
decrby key increment
实例
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> incr num 11
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> incrby num 11
(integer) 13
127.0.0.1:6379> decrby num 12
(integer) 1
string类型数据的总结
-
string在redis内部存储默认就是一个字符串,当遇到增减类操作incr, decr时会转成数值型进行计算
-
redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响。
注意: 按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错(数据范围与long类型的数据范围一致)
127.0.0.1:6379> set key ddd
OK
127.0.0.1:6379> incr key 1
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> incrby key 1 // string是'ddd',所有无法进行自增/减
(error) ERR value is not an integer or out of range
127.0.0.1:6379>
2-2-3 Redis中String类型应用2:设置数据指定的生命周期
应用场景:
1)每个微信号每 4 小时只能投1票。
2)每种商品热门期维持3天, 3天后自动取消热门.
3)热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性。
设置数据的生存周期指令
setex key seconds value
psetex key milliseconds value
- redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
2-2-4 Redis中String类型应用3:各种结构型和非结构型高热度数据访问加速
实例:微博用户粉丝数,关注数,微博数的显示。
采用redis存储,value就是粉丝数/关注数/微博数目。key的名称通常按照以下规则设定:
表名 | 主键名 | 主键值 | 字段值 |
---|---|---|---|
具体实现:
方式1:以用户主键和属性值作为key,后台设定定时刷新策略
127.0.0.1:6379> set user:id:3506728370:fans 12210947
OK
127.0.0.1:6379> set user:id:3506728370:blogs 6164
OK
127.0.0.1:6379> set user:id:3506728370:focuss 83
OK
127.0.0.1:6379> get user:id:3506728370:focuss
"83"
127.0.0.1:6379> incr user:id:3506728370:focuss
(integer) 84
方式2:在redis中以json格式存储用户信息作为value,key采用表名+主键名+主键id,定时刷新(也可以使用hash类型)
2-2-5 redis中String数据使用注意点
数据操作不成功的反馈与数据正常操作之间的差异
string 类型数据操作的注意事项
1)表示运行结果是否成功
(integer) 0 → false 失败
(integer) 1 → true 成功
2)表示运行结果值
(integer) 3 → 3 3个
(integer) 1 → 1 1个
3)数据未获取到
(nil)等同于null
4)数据最大存储量
512MB
5)数值计算最大范围( java中的long的范围)
2-3 hash类型数据
注意:hash数据是指value的类型是hash表
2-3-1 hash类型数据的定义与使用
特点:单个存储空间保存多个键值对数据,适用于对一系列存储的数据进行编组,方便管理。
基本命令
/*数据的基本操作*/
hset key field value
hget key field
hgetall key
hdel key field1 [field2]
hmset key field1 value1 field2 value2 // 添加/修改多个数据
hmget key field1 field2 … // 获取多个数据
hlen key // 获取哈希表中字段的数量
hexists key field // 获取哈希表中是否存在指定的字段
/*获取哈希表中所有的字段名或字段值*/
hkeys key
hvals key
/*设置指定字段的数值数据增加指定范围的值*/
hincrby key field increment
hincrbyfloat key field increment
实例
127.0.0.1:6379> hset user name zhangsan // 设置单个hash类型数据
(integer) 1
127.0.0.1:6379> hset user age 38
(integer) 1
127.0.0.1:6379> hset user weight 80
(integer) 1
127.0.0.1:6379> hgetall user // 显示hash类型数据所有的key与value
1) "name"
2) "zhangsan"
3) "age"
4) "38"
5) "weight"
6) "80"
127.0.0.1:6379> hget user name // 根据value的field获取值
"zhangsan"
127.0.0.1:6379> hdel user weight
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "zhangsan"
3) "age"
4) "38"
127.0.0.1:6379> hmset name dog age 11 // 批量修改值
(error) ERR wrong number of arguments for HMSET
127.0.0.1:6379> hmset user name dog age 11
OK
127.0.0.1:6379> hgetall user
1) "name"
2) "dog"
3) "age"
4) "11"
127.0.0.1:6379> hlen user // 查看value中field的数量
(integer) 2
2-3-2 Redis中hash类型数据的使用注意点
1)hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,对应的值为( nil)
2)每个 hash 可以存储 232 - 1 个键值对
3)hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
4)hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈 。
2-3-3 redis的hash类型数据应用1:实现购物车
实现策略:
存储结构:
- 每个用户id作为key
- value是hash类型数据,其中商品id是field,商品的数量则是该field对应的数值。
数据操作方式:
- 添加商品:追加全新的field与value
- 浏览:遍历hash
- 更改数量
hincrby
- 删除商品:删除
hdel
方案注意点:redis仅仅能够实现购物车的redis存储模型,添加、浏览、更改数量、删除、清空
购物车实际实现时需要考虑的问题:
购物车于数据库间持久化同步
购物车于订单间关系
提交购物车:读取数据生成订单
商家临时价格调整:隶属于订单级别
未登录用户购物车信息存储
cookie存储
redis如何加速购物车数据的呈现?
数据设计:
- key是用户id
- value是hash类型数据,具有2个field(key:value键值对):
- 第一个key:value即key(商品id:nums),value(商品数量) (每个用户私有的数据)
- 第二个key:value即key商品id:nums),value(商品的信息,json格式) (商品信息数据是可以共享的,并非用户私有的)
127.0.0.1:6379> hmset 003 G01:nums 100 G01:info {....} // hmset 用户id key1 该商品在购物车数量 key2 该商品信息
OK
127.0.0.1:6379> hgetall 003
1) "G01:nums"
2) "100"
3) "G01:info"
4) "{....}"
注意:第二个key:value信息可以抽取出来作为公共信息获取(独立的hash),避免相同的数据反复查询。
特别的命令
//插入(如果已存在同名的field,会被覆盖)
hset key field value
hmset key field1 value1 field2 value2...
//插入(如果已存在同名的field,不会被覆盖)
hsetnx key field value
hash数据类型其他的应用场景:redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
2-4 list类型数据
2-4-1 list的特点与基本命令
特点
- 数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
- list类型:保存多个数据,底层使用双向链表存储结构实现
基本命令
// 添加修改数据,lpush为从左边添加,rpush为从右边添加
lpush key value1 value2 value3...
rpush key value1 value2 value3...
//查看数据, 从左边开始向右查看. 如果不知道list有多少个元素,end的值可以为-1,代表倒数第一个元素
//lpush先进的元素放在最后,rpush先进的元素放在最前面
lrange key start end
//得到长度
llen key
//取出对应索引的元素
lindex key index
//获取并移除元素(从list左边或者右边移除)
lpop key
rpop key
//规定时间内获取并移除数据,b=block,给定一个时间,如果在指定时间内放入了元素,就移除
blpop key1 key2... timeout
brpop key1 key2... timeout
//移除指定元素 count:移除的个数 value:移除的值。 移除多个相同元素时,从左边开始移除
lrem key count value
实例
127.0.0.1:6379> lpush list1 huawei
(integer) 1
127.0.0.1:6379> lpush list1 apple
(integer) 2
127.0.0.1:6379> lpush list1 microsoft
(integer) 3
127.0.0.1:6379> lrange list1 start stop
1) "microsoft"
2) "apple"
3) "huawei"
127.0.0.1:6379> lindex list1 1
"apple"
127.0.0.1:6379> lrange list1 0 -1
1) "microsoft"
2) "apple"
3) "huawei"
2-4-2 redis中list的应用1:具有操作顺序先后的数据的控制
实际场景:微信朋友圈的点赞,需要按照点赞顺序显示好友的信息,如果取消点赞则移除对应好友的信息。
2-4-3 Redis中list数据类型的应用2:最新消息展示
实际场景:
1)twitter、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示
2)粉丝列表需要将最近关注的粉丝列在前面
3) 新闻、资讯类网站如何将最新的新闻或资讯按照发生的时间顺序展示
4) 企业运营过程中,系统将产生出大量的运营数据,保障多台服务器操作日志的统一顺序输出
解决策略
解决方案
依赖list的数据具有顺序的特征对信息进行管理
使用队列模型解决多路信息汇总合并的问题
使用栈模型解决最新消息的问题
2-4-4 list数据类型使用注意点
- list中保存的数据都是string类型的,数据总容量是有限的,最多232 - 1 个元素 (4294967295)。
- list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作
- 获取全部数据操作结束索引设置为-1
- list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载(加快数据的显示)
2-5 set类型数据
2-5-1 set数据特点以及基本命令
特点
- 存储大量的数据,在查询方面提供更高的效率
- 与hash存储结构完全相同,仅存储键,不存储值( nil),并且键是不允许重复的
基本操作命令
//添加元素
sadd key member1 member2...
//查看元素
smembers key
//移除元素
srem key member
//查看元素个数
scard key
//查看某个元素是否存在
sismember key member
//从set中任意选出count个元素
srandmember key count
//从set中任意选出count个元素并移除
spop key count
//求两个集合的交集、并集、差集
sinter key1 key2...
sunion key1 key2...
sdiff key1 key2...
//求两个set的交集、并集、差集,并放入另一个set中
sinterstore destination key1 key2...
sunionstore destination key1 key2...
sdiffstore destination key1 key2...
//求指定元素从原集合放入目标集合中
smove source destination key
2-5-2 redis中set应用1:随机推荐类信息检索
redis 应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐,大V推荐等
实际场景:每位用户首次使用今日头条时会设置3项爱好的内容,但是后期为了增加用户的活跃度、兴趣点,必须让用户
对其他信息类别逐渐产生兴趣,增加客户留存度,如何实现?
使用set类型数据实现: 用户关注信息分类中的热点信息 + 其他类别的挑选的热点信息结合 = 总的信息结合 => 总的信息集合中随机挑选一部分信息作为最终展示
set中提供了随机选择集合中数据的方法:
srandmember key [count] // 随机获取集合中指定数量的数据
spop key [count] // 随机获取集合中的某个数据并将该数据移出集合
2-5-3 redis中set应用2:同类信息的关联搜索,二度关联搜索,深度关联搜索
具体应用场景:
- 显示共同关注(一度)
- 显示共同好友(一度)
- 由用户A出发,获取到好友用户B的好友信息列表(一度)
- 由用户A出发,获取到好友用户B的购物清单列表(二度)
- 由用户A出发,获取到好友用户B的游戏充值列表(二度)
2-5-4 redis中set去重应用3:统计网站的PV(Page View),UV(Unique Visitor,) ,IP(独立IP)。
业务场景:公司对旗下新的网站做推广,统计网站的PV(访问量) ,UV(独立访客) ,IP(独立IP)。
- PV:网站被访问次数,可通过刷新页面提高访问量
- UV:网站被不同用户访问的次数,可通过cookie统计访问量,相同用户切换IP地址, UV不变
- IP:网站被不同IP地址访问的总次数,可通过IP地址统计访问量,相同IP不同用户访问, IP不变
解决方案
* 利用set集合的数据去重特征,记录各种访问数据
* 建立string类型数据,利用incr统计日访问量( PV)
* 建立set模型,记录不同cookie数量( UV)
* 建立set模型,记录不同IP数量( IP)
2-5-5 redis中set应用4:基于黑名单与白名单设定的服务控制
业务场景:
黑名单的作用:基于技术层面区分出爬虫用户后,需要将此类用户进行有效的屏蔽,这就是黑名单的典型应用。
- 资讯类信息类网站追求高访问量,但是由于其信息的价值,往往容易被不法分子利用,通过爬虫技术,
快速获取信息,个别特种行业网站信息通过爬虫获取分析后,可以转换成商业机密进行出售。例如第三方火
车票、机票、酒店刷票代购软件,电商刷评论、刷好评。 - 爬虫带来的伪流量也会给经营者带来错觉,产生错误的决策,有效避免网站被爬虫反复爬取成为每
个网站都要考虑的基本问题 - 有些小型网站需要爬虫为其带来一些流量。
白名单的作用:对于安全性更高的应用访问,仅仅靠黑名单是不能解决安全问题的,此时需要设定可访问的用户群体,
依赖白名单做更为苛刻的访问验证。
解决方案(利用set集合维护黑名单)
基于经营战略设定问题用户发现、鉴别规则
周期性更新满足规则的用户黑名单,加入set集合
用户行为信息达到后与黑名单进行比对,确认行为去向
黑名单过滤IP地址:应用于开放游客访问权限的信息源
黑名单过滤设备信息:应用于限定访问设备的信息源
黑名单过滤用户:应用于基于访问权限的信息源
2-5-6 set类型的数据使用注意事项
- set 类型不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份
- set 虽然与hash的存储结构相同,但是无法启用hash中存储值的空间
2-6 sortedSet类型数据
2-6-1 sortedset数据特点以及基本命令
sortedset:需要对数据的进行有序的展示
与set类型数据的区别:除了key以外增加了score列
基本命令
//插入元素, 需要指定score(用于排序)
zadd key score1 member1 score2 member2
//查看元素(score升序), 当末尾添加withscore时,会将元素的score一起打印出来
zrange key start end (withscore)
//查看元素(score降序), 当末尾添加withscore时,会将元素的score一起打印出来
zrevrange key start end (withscore)
//移除元素
zrem key member1 member2...
//按条件获取数据, 其中offset为索引开始位置,count为获取的数目
zrangebyscore key min max [withscore] [limit offset count]
zrevrangebyscore key max min [withscore] [limit offset count]
//按条件移除元素
zremrangebyrank key start end
zremrangebysocre key min max
//按照从大到小的顺序移除count个值
zpopmax key [count]
//按照从小到大的顺序移除count个值
zpopmin key [count]
//获得元素个数
zcard key
//获得元素在范围内的个数
zcount min max
//求交集、并集并放入destination中, 其中numkey1为要去交集或并集集合的数目
zinterstore destination numkeys key1 key2...
zunionstore destination numkeys key1 key2...
//查看某个元素的索引(排名)
zrank key member
zrevrank key member
//查看某个元素索引的值
zscore key member
//增加某个元素索引的值
zincrby key increment member
注意
- min与max 用于限定搜索查询的条件
- start与stop用于限定查询范围,作用于索引,表示开始和结束索引
- offset与count用于限定查询范围,作用于查询结果,表示开始位置和数据总量
实例
127.0.0.1:6379> zadd scores 94 zs
(integer) 1
127.0.0.1:6379> zadd scores 100 ls
(integer) 1
127.0.0.1:6379> zadd scores 60 ww
(integer) 1
127.0.0.1:6379> zadd scores 47 zl
(integer) 1
127.0.0.1:6379> zrange scores 0 -1
1) "zl"
2) "ww"
3) "zs"
4) "ls"
127.0.0.1:6379> zrange scores 0 -1 WITHSCORES
1) "zl"
2) "47"
3) "ww"
4) "60"
5) "zs"
6) "94"
7) "ls"
8) "100"
127.0.0.1:6379> zrevrange scores 0 -1
1) "ls"
2) "zs"
3) "ww"
4) "zl"
127.0.0.1:6379> zrem scores ww
(integer) 1
2-6-2 redis中sortedsort的应用1: 排行榜功能的实现
业务场景:
票选广东十大杰出青年,各类综艺选秀海选投票,各类资源网站TOP10(电影,歌曲,文档,电商,游戏等)聊天室活跃度统计游戏好友亲密度,为所有参与排名的资源建立排序依据
实现策略:利用redis的sortedsort显示排名
//查看某个元素的索引(排名)
zrank key member
zrevrank key member
//查看某个元素索引的值
zscore key member
//增加某个元素索引的值
zincrby key increment member
2-6-4 redis中sortedsort的应用2: 定时任务执行顺序管理或任务过期管理
业务场景
- 用户VIP到期管理
- 投票、讨论,限时进行,逾期作废管理
实现策略
基本思想:对于基于时间线限定的任务处理,将处理时间作为redis的sortedset的score值,利用排序功能区分处理的先后顺序
- 当到期后处理对应任务,移除redis中的记录,并记录下一个要处理的时
- 当新任务加入时,判定并更新当前下一个要处理的任务时间
- 为提升sorted_set的性能,通常将任务根据特征存储成若干个sorted_set。例如1小时内, 1天内,
月内,季内,年度等,操作时逐级提升,将即将操作的若干个任务纳入到1小时内处理的队列中
2-6-5 redis中sortedsort的应用3: 即时任务/消息队列执行管理
业务场景:任务/消息权重设定应用
当任务或者消息待处理,形成了任务队列或消息队列时,对于高优先级的任务要保障对其优先处理
实现策略:
- 对于带有权重的任务,优先处理权重高的任务,将任务的权重作为sortedset中score即可
如果排序的指标有多个,但是score只有一个,该如何设计score权重?(多条件任务权重设定 )
实例:
指标1:外贸订单优先于国内订单
指标2:总裁订单优先于员工订单,经理订单优先于员工订单
score设计策略:先设定订单类别,后设定订单发起角色类别,整体score长度必须是统一的,不足位补0。
- 例如外贸101,国内102,经理004,员工008,则员工下的外贸单score值为101008(优先),经理下的国内单score值为102004 。
2-6-6 sortedset的使用注意点
sortedsort中score的注意点(score是排序的依据):
- score保存的数据存储空间是64位,整数范围就是long的范围
- score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时
候要慎重 - sorted_set 底层存储还是基于set结构的,数据不能重复,如果重复, score值将被反
复覆盖,保留最后一次修改的结果
3 redis的各种数据类型的综合应用
3-1 业务场景:限制用户每分钟的服务使用次数(10次)
人工智能领域的语义识别与自动对话将是未来服务业机器人应答呼叫体系中的重要技术,百度自研用户评价语义识别服务,免费开放给企业试用,同时训练百度自己的模型。现对试用用户的使用行为进行限速,限制每个用户每分钟最多发起10次调用
解决方法
step1:由用户进行服务调用,先根据用户的uid判断当前用户是否再redis中有记录。
step2:情况1:没有记录,则新建一个生命周期为60s的string记录,并将次数累加。情况2:有记录,判断次数是否已达上限,没有则累加,有则拒绝提供服务,知道记录消失,即用户可在一个时间段获取用户访问的次数。
上面的解决方案中每次用户访问都需要判断使用次数是否已达上限,这个判断可以通过将初始值设置为 Long.MAX_VALUE-访问次数 。
- 遇到异常即+操作超过上限,视为使用达到上限
实际操作
127.0.0.1:6379> get 415 // 判断该用户关联记录是否存在
(nil)
127.0.0.1:6379> setex 415 60 9223372036854775797 // 设置记录初始值为 Long.MAX_VALUE-10,记录生命周期为60s
OK
127.0.0.1:6379> incrby 415 10 // 60s内用户的访问次数达到10次
(integer) 9223372036854775807
(2.08s)
127.0.0.1:6379> incr 415 // 60s内用户第11次访问
(error) ERR increment or decrement would overflow // 60s访问次数达到上限,数值溢出,抛出异常,拒绝为用户提供服务
127.0.0.1:6379> incr 415
(error) ERR increment or decrement would overflow
127.0.0.1:6379> incr 415
(error) ERR increment or decrement would overflow
127.0.0.1:6379> incr 415
(error) ERR increment or decrement would overflow
127.0.0.1:6379> incr 415 // 60s到达,老的用户记录消失,用户又可以获取10次服务调用
(integer) 1
3-2 业务场景:**基于时间顺序的数据操作,而不关注具体时间 **
场景介绍
使用微信的过程中,当微信接收消息后,会默认将最近接收的消息置顶,当多个好友及关注的订阅号同时发
送消息时,该排序会不停的进行交替。同时还可以将重要的会话设置为置顶。一旦用户离线后,再次打开微
信时,消息的显示方法
解决策略
依赖list的数据具有顺序的特征对消息进行管理,将list结构作为栈使用
对置顶与普通会话分别创建独立的list分别管理
当某个list中接收到用户消息后,将消息发送方的id从list的一侧加入list(此处设定左侧)
多个相同id发出的消息反复入栈会出现问题,在入栈之前无论是否具有当前id对应的消息,先删除对应id
推送消息时先推送置顶会话list,再推送普通会话list,推送完成的list清除所有数据
消息的数量,也就是微信用户对话数量采用计数器的思想另行记录,伴随list操作同步更新
3-3 redis的各种数据类型应用汇总(重要)
Tips 1: redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
Tips 2: redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
Tips 3: redis应用于各种结构型和非结构型高热度数据访问加速
Tips 4: redis 应用于购物车数据存储设计
Tips 5: redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
Tips 6: redis 应用于具有操作先后顺序的数据控制
Tips 7: redis 应用于最新消息展示
Tips 8: redis 应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐,大V推荐等
Tips 9: redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索
Tips 10: redis 应用于同类型不重复数据的合并、取交集操作
Tips 11: redis 应用于同类型数据的快速去重
Tips 12: redis 应用于基于黑名单与白名单设定的服务控制
Tips 13: redis 应用于计数器组合排序功能对应的排名
Tips 14: redis 应用于定时任务执行顺序管理或任务过期管理
Tips 15: redis 应用于及时任务/消息队列执行管理
Tips 16: redis 应用于按次结算的服务控制
Tips 17: redis 应用于基于时间顺序的数据操作,而不关注具体时间
4 redis中key的通用操作
4-1 Key的特征
- key是一个字符串,通过key获取redis中保存的数据
4-2 Key的操作
基本操作
//查看key是否存在
exists key
//删除key
del key
//查看key的类型
type keyCopy
拓展操作(时效性操作)
//设置生命周期
expire key seconds
pexpire key milliseconds
//查看有效时间, 如果有有效时间则返回剩余有效时间, 如果为永久有效,则返回-1, 如果Key不存在则返回-2
ttl key
pttl key
//将有时限的数据设置为永久有效
persist keyCopy
拓展操作(查询操作)
//根据key查询符合条件的数据
keys patternCopy
查询规则
拓展操作(其他操作)
//重命名key,为了避免覆盖已有数据,尽量少去修改已有key的名字,如果要使用最好使用renamenx
rename key newKey
renamenx key newKey
//查看所有关于key的操作, 可以使用Tab快速切换
help @genericCopy
5 redis中数据库通用操作
5-1 数据库
- Redis为每个服务提供有16个数据库,编号从0到15
- 每个数据库之间的数据相互独立
5-2 基本操作
//切换数据库 0~15
select index
//其他操作
quit
ping
echo massageCopy
5-3 拓展操作
//移动数据, 必须保证目的数据库中没有该数据
mov key db
//查看该库中数据总量
dbsize