数据存储类型介绍
redis数据存储格式
- redis自身是一个Map,其中所有的数据都是采用key:value的形式存储
- 数据类型指的是存储的数据的类型,也就是value部分的类型,key部分永远都是字符串
string
和String相似
- 存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
- 存储数据的格式:一个存储空间保存一个数据
- 存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用
set name feifei
set age 18
del age
get name
*添加/修改多个数据 mset key1 value1 key2 value2 m:multiple多个
*获取多个数据 mget key1 key2...
*获取数据字符个数 strlen key
*追加信息到原始信息后部(如果原始信息存在就追加,否则新建) append key value
string类型数据的扩展操作
-
业务场景
大型企业级应用,分表是基本操作,使用多张表存储同类型的数据,但是对应的主键id必须保证统一性,不能重复。mysql怎么解决
解决方案
-
设置数值数据增加指定范围的值
incr key incrby key increment incrbyfloat key increment
-
设置数值减少指定范围的值
decr key decrby key increment
-
string作为数值操作
- string在redis内部默认是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算
- redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个个执行的,因此无需考虑并发带来的数据影响
- 注意:按数值
-
-
业务场景2
投票:只能通过微信号投票,每个微信号每四个小时只能投一票 电商热门商品推荐,热门商品不能一直处于热门期,每种商品热门维持3天,3天后自动取消热门 新闻网站出现热点新闻,热点新闻是时效性的,如何自动控制新闻的时效性
-
设置数据具有指定的生命周期
setex key seconds value psetex key milliseconds value
-
redis控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有失效性限定控制的操作
-
-
注意事项
key的设置约定
- 数据库中的热点数据key命名惯例
- 表名:主键名:主键指:字段名
hash
和HashMap相似
- 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应对应用存储对象信息
- 需要的存储结构:一个存储空间保存多个键值对数据
hash存储结构优化:
- 如果field数量较少,存储结构优化为类数组结构
- 如果filed数量较多,存储结构使用hashmap结构
*添加/修改数据
hset key filed value
*获取数据
hget key filed
hgetall key
*删除数据
hdel key filed1 [filed2]
*添加/修改多个数据
hmset key field1 value1 filed2 value2
*获取多个数据
hmget key filed1 filed2...
*获取hash表中字段的数量
hlen key
*获取哈希表中是否存在指定的字段
hexists key filed
*获取哈希表中所有的字段名或者字段值
hkeys key
hvals key
*设置指定字段的数值数据增加指定范围的值
hincrby key filed increment
hincrbyfloat key field increment
hash类型数据操作的注意事项
- hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象,如果数据未获取到,对应的值为nil
- hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性,但hash设计初衷不是为了存储大量对象而设计的,切记不可以乱用,更不能将hash作为对象列表使用
- hgetall 操作可以获取全部属性,如果内部filed过多,整体遍历数据效率就会很低。有可能成为数据访问的瓶颈
hash类型应用场景:
-
每条购物车中的商品记录保存成两条filed
-
filed1专用于保存购买数量
- 命名格式:商品id:nums
- 保存数据:数值
-
filed2专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等
- 命名格式:商品id:info
- 保存数据:json
hsetnx key field value
hash实现抢购
解决方案
- 以商家id作为key
- 将参与抢购的商品id作为field
- 将参与抢购的商品数量作为对应的value
- 抢购时使用降值得方式控制产品数量
业务场景
string存储对象json与hash
string主要是读存操作
hash涉及到更改使用hash更为方便
list
和LinkedList相似
- 数据存储需求:存储多个数据,并对数据进入存储空间得顺序进行区分
- 需要得存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
- list类型:保存多个数据,底层使用双向链表存储结构实现
list类型数据基本操作
* 添加/修改数据
lpush key value1 【value2】
rpush key value1 [value2]
* 获取数据
lrange key start stop
lindex key index
llen key
* 获取并移除数据
lpop key
rpop key
list类型数据扩展操作
- 规定时间内获取并且移除数据
blpop key1 【key2】 timeout
brpop key2 [key2] timeout
业务场景
微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息
移除指定数据
lrem key count value
list操作注意事项
- list中保存得数据都是string类型得,数据得总容量也是有限得
- list具有索引得概念,但是操作得时候通常以队列得形式进行入队出队操作,或者以栈得形式进行入栈操作
- 获取全部数据操作结束索引设置为1
- list可以对数据进行分页操作,通常第一页得信息来自于list,第二页及更多得信息通过数据库得形式进行加载
set
和Hashset相似
- 新的存储需求:存储大量的数据,在查询方面提供更高效的效率
- 需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
- set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的
set类型数据的基本操作
添加数据
sadd key member1 [member2]
获取全部数据
smembers key
删除数据
srem key member1 [member2]
获取集合数据总量
scard key
判断集合中是否包含指定数据
sismember key member
set类型数据的扩展操作
-
业务场景
每位用户首次使用今日头条时会设置3项爱好的内容,但是后期为了增加用户的活跃度、兴趣点,必须让用户对其他信息类型逐渐产生兴趣,增加客户留存度,如何实现?
-
业务分析
- 系统分析出各个分类的最新或者最热信息条目并组织成set集合
- 随机挑选其中部分信息
- 配合用户关注信息分类中的热点信息组织成展示的全信息集合
-
解决方案
-
随机获取集合中指定数量的数据 srandmember key [count]
-
随机获取集合中的某个数据并将该数据移除集合 spop key
-
-
求两个集合的交集 sinter key1 [key2] 求两个集合的并集 sunion key1 [key2] 求两个集合的差集 sdiff key1 [key2] 求两个集合的交、并、差集并存储到指定集合中 sinterstore destination key1 [key2] sunionstore destination key1 [key2] sdiffstore destination key1 [key2] 将指定数据从原始集合中移动到目标集合中 smove source destination member
set类型数据操作的注意事项
- set类型不允许数据重复,如果添加的数据在set中已经存在,将只保留一份
- set虽然与hash存储结构类似,但是无法在set中启用hash的存储方式
-
应用场景
-
业务场景
公司对旗下新的网站做推广,统计网站得pv、uv、ip
pv:网站被访问得次数,可以通过刷新页面提高访问量
uv:网站被不同用户访问得次数,可以通过cookie统计访问量,相同 用户切换ip地址,uv不变
ip:网站被不同ip地址访问得总次数,可通过ip地址统计访问量,相同ip不同用户访问,ip不变
-
解决方案
- 利用set集合得数据去重特征,记录各种访问数据
- 建立string类型数据,利用incr统计日访问量(pv)
- 建立set模型,记录不同cookie数量(uv)
- 建立set模型,记录不同ip数量(ip)
-
sorted_set
和TreeSet相似
- 新的存储需求:数据排序有利于数据得有效展示,需要提供一种可以根据自身特征进行排序的方式
- 需要的存储结构:新的存储模型,可以保存可排序的字段
- sorted_set类型:在set的存储结构基础上添加可排序字段
sorted_set类型数据的基本操作
添加数据
zadd key score1 member1 [score2 member2]
获取全部数据
zrange key start stop [withscores]
zrevrange key start stop [withscores]
删除数据
zrem key member [member...]
按条件获取数据 limit和mysql 里的limit一样的作用
zrangebyscore key min max [withscores] [limit]
zrevrangebyscore key max min [withscores]
条件删除
zremrangebyrank key start stop
zremrangebyscore key min max
注意:
- min与max用于限定搜索查询的条件
- start与stop用于限定查询范围,作用于索引,表示开始和结束索引
- offset与count用于限定查询范围,作用域查询结果,表示开始位置和数据总量
获取集合数据总量
zcard key
zcount key min max
集合交、并操作
zinterstore destination numkeys key [key ...]
zunionstore destination numkeys key [key ...]
集合交、并操作默认是将score进行相加
但是如果在命令最后加上aggregate 聚合函数 则可以根据聚合函数改变score的取值方式 例如
zinterstore sss 2 feifei zz aggrement max
结果集中的member是两个zset中都有的 且score为score大的那个的分值
sorted_set类型数据的扩展操作
热点的排名:例如聊天最多好友的排名等等
解决方案
获取对应的索引
zrank key member
zrerank key member
score值得获取与修改
zscore key member
zincrby key increment member
sorted_set 类型数据操作得注意事项
- score保存得数据存储空间是64位 如果是整数范围是-9007199254740992~9007199254740992
- score保存得数据也可以是一个双精度得double值,基于双精度浮点数得特征,可能会丢失精度,使用的时候要慎重
- sorted_set底层存储还是基于set结构得,因此数据不能够重复,如果重复添加相同得数据,score值将被反复覆盖,保存最后一次修改得结果
数据类型实践
限制使用次数得场景
某试用产品,开放个接口给用户,但是用户免费使用得时候每分钟内只可以使用该接口10次
解决方案:
- 设计计数器,记录调用次数,用于控制业务执行次数,以用户id作为key,使用次数作为value
- 在调用前获取次数,判断是否超过限定次数
- 不超过次数得情况下,每次调用计数+1
- 业务调用失败,计数-1
- 为计数器设置生命周期为指定周期,例如1秒/分钟,自动清空周期内使用次数
但是这样得操作在每次使用得时候都要判断值是否超过每分钟内得使用得最大次数,于是我们可以将设置得值不是从1开始而是从9223…5797开始在进行在进行9次后,第十次incr会超过最大值,redis会报错这样就不用每次都去判断是否超过单位分钟内得最大使用次数了
微信会话消息管理
使用微信的过程中,当微信接收到消息后,会默认将最近接收的消息置顶,当多个好友及关注的订阅号同时发送消息时,该排序会不停的进行交替。同时还可以将重要的会话设置为置顶。一旦用户离线后,再次打开微信时,消息该按什么样的顺序显示
解决方案:
- 依赖list的数据具有顺序的特征对消息进行管理,将list结构作为栈使用
- 对置顶于普通会话分别创建独立的list分别管理
- 当某个list中接收到用户消息后,将消息发送方的id从list的一侧加入list(此处设定为左侧)
- 多个相同id发出的消息反复入栈会出现问题,在入栈前无论是否具有当前id对应的消息,先删除对应id
- 推送消息时先推送指定会话list,再推送普通会话list,推送完成的list清除所有数据
- 消息的数量,也就是微信用户对话数量采用计数器的思想另行记录,伴随list操作同步更新
通用命令
key特征
- key是一个字符串,通过key获取redis中的数据
- 对于key自身状态的相关操作,例如:删除、判定存在,获取类型等
- 对于key有效性控制相关操作,例如:有效期设定,判定是否有效、有效状态的切换等
- 对于key快速查询操作,例如按指定策略查询key
删除指定key
del key
获取key是否存在
exists key
获取key的类型
type key
扩展操作
为指定key设置有效期
expire key seconds
pexpire key milliseconds
expireat key timestamp 使用时间戳
pexpireat key milliseconds-timestamp
获取key的有效时间
ttl key
pttl key
切换key从时效性转换为永久性
persist key
查询key
keys pattern
* 匹配任意数量的任意符号
? 配合一个任意符号
[] 匹配一个指定符号
为key改名
rename key newkey 改为已经存在的会覆盖数据
renamenx key newkey 如果不存在的话再去改名
对所有key排序
sort list desc/asc
其他key通用操作
help @generic
关于redis db的一些常用指令
* 切换数据库
select index
* 其他操作
quit
ping
echo message
数据移动
move key db
数据删除
dbsize 库的key数量
flushdb 删除当前库
flushall 删除全部