Redis在项目中的地位及使用场景剖析

⼀、 redis 特点
 
所有数据存储在内存中,高速读写 提供丰富多样的数据类型: string hash set sorted set bitmap hyperloglog 提供了 AOF RDB 两种数据的持久化保存⽅式,保证了 Redis 重启后数据不丢失 Redis 的所有操作都是原⼦性的,还⽀持对⼏个操作合并后的原⼦性操作,⽀持事务。
 
通常我们都把数据存到关系型数据库中,但为了提升应⽤的性能,我们应该把访频率⾼且不会经常变 动的数据缓存到内存中。 Redis 没有像 MySQL 这类关系型数据库那样强⼤的查询功能,需要考虑如何 把关系型数据库中的数据,合理的对应到缓存的 key-value 数据结构中。
 
⼆、 设计 Redis Key
 
使用冒号把 key 中要表达的多种含义分开表示,步骤如下:
1. 把表名转化为 key 前缀
2. 主键名(或其他常⽤于搜索的字段)
3. 主键值
4. 要存储的字段。
 
eg. ⽤户表( user
idnameemail
1lx3333@222.com
2ab

444@222.com

 
 
 
 
 
 
 
 
这个简单的表可能经常会有这个的需求: > 根据⽤户 id 查询⽤户邮箱地址,可以选择把邮箱地址这个数 据存到 redis 中:
set user:id:1:email 3333@222.com;
set user:id:2:email 444@222.com;
三、 String 数据类型的应⽤场景
 
1. 简介
string 类型是 Redis 中最基本的数据类型,最常⽤的数据类型,甚⾄被很多玩家当成 redis 唯⼀的数 据类型去使⽤。 string 类型在 redis 中是⼆进制安全 (binary safe) , 这意味着 string 值关⼼⼆进制的字符 串,不关⼼具体格式,你可以⽤它存储 json 格式或 JPEG 图⽚格式的字符串。  
 
2. 数据模型
string 类型是基本的 Key-Value 结构, Key 是某个数据在 Redis 中的唯⼀标识, Value 是具体的数据。
keyvalue
'name''redis'
'type''string'
 
 
 
 
 
 
 
 
 
3. 应⽤场景
 
(1) 存储 MySQL 中某个字段的值
key 设计为 表名:主键名:主键值:字段名 eg.
 
(2) 存储对象
string 类型⽀持任何格式的字符串,应⽤最多的就是存储 json 或其他对象格式化的字符串。 ( 这种场景下推荐使⽤ hash 数据类型 )
set user:id:1 '[{"id":1,"name":"zj","email":"10000@qq.com"},]'
(3) ⽣成⾃增 id
redis string 类型的值为整数形式时, redis 可以把它当做是整数⼀样进行自增( incr )自减( decr) 操作。由于 redis 所有的操作都是原⼦性的,所以 不必担⼼多客户端连接时可能出现的事务 问题。 incr 对值进⾏加 1 操作,如果不是整数,返回错误,如果不存在按照从 0 开始 decr incr ,但是是减 1 操作 incrby,decrby ,增加减去指定的数
 
(4) ⽣成⾃增 id
⽐如视频播放次数,点赞次数。
 
(5) 共享 session
数据共享的功能, redis 作为单独的应用软件用来存储⼀些共享数据供多个实例访问。
 
(6) ⾃动定时过期
set key value [ex seconds] [px millseconds] [nx|xx]
ex seconds: 键过期时间
px milliseconds: 为键设置毫秒级过期时间
nx: 键必须不存在才可以设置成功,⽤于添加
xx: 键必须存在,才可以设置成功,⽤于更新
 
(7) 批量操作
 
mset,mget 批量设置和获取命令,在操作多个 key 的时候可以节省⽹络传输时间
 
mset key value [key value...]
mget key [key ...]
四、 hash 数据类型的应⽤场景
 
1. 简介
hash 类型很像⼀个关系型数据库的数据表, hash Key 是⼀个唯⼀值, Value 部分是⼀个 hashmap 的结构。
 
2. 数据模型
假设有⼀张数据库表如下:
 
idnametype
1redishash

 

 
 
 
 
如果要用 redis hash 结构存储,数据模型如下:
 
 
hash 数据类型在存储上述类型的数据时具有⽐ string 类型更灵活、更快的优势,具体的说,使⽤ string 类型存储,必然需要转换和解析 json 格式的字符串,即便不需要转换,在内存开销⽅⾯,还是 hash 占优势。 和字符串很像,基本上 redis 对字符串操作的命令 ,Redis Hash ⼀般也存在,不过在命令前 多个⼀个 h
 
3. 应⽤场景
 
hash 类型⼗分适合存储对象类数据,相对于在 string 中介绍的把对象转化为 json 字符串存储, hash 的结
构可以任意添加或删除 字段名 ,更加⾼效灵活。 ⼀些关系型数据库中不是特别复杂的表,也无需复杂
的关系查询,可以使⽤ Redis Hash 来存储,也可以⽤ Hash 做表数据缓存。
hmset user:1 name zj email 123456@163.com
hset key field value
hsetnx key field value //与setnx命令⼀样,不存在则设置值,⽤于添加,作⽤在field上⾯
hget key field //获取值
hdel key field // 删除值
hlen key //⼦酸field的个数
hmset key field value [filed value] //批量设置field-value
hexists key field //判断filed是否存在
hkeys key //获取所有的field
hvals key //获取所有的value
hgetall key //获取所有的field-value ,如果元素数较多会存在阻塞redis的可能
hincreby key filed
五、 list 数据类型的应⽤场景
 
1. 简介
list 是按照插⼊顺序排序的字符串链表,可以在头部和尾部插⼊新的元素(双向链表实现,两端添 加元素的时间复杂度为 O(1) )。插⼊元素时,如果 key 不存在, redis 会为该 key 创建⼀个新的链表,如 果链表中所有的元素都被移除,该 key 也会从 redis 中移除。
 
2. 数据模型
 
列表⽤来存储多个有序的字符串,⼀个列表最多可以存储 2^32 - 1 个元素,在 redis 中可以对列表的两 端插⼊ push 和弹出 pop ,还可以取指定范围的元素。常见操作时用 lpush 命令在 list 头部插⼊元素, 用 rpop 命令在 list 尾取出数据。
rpush key value [value...] //从右插⼊元素
lpush key value [value...] //从左边插⼊元素
lrange key start end //获取指定范围的元素列表
lindex key index //获取列表指定索引下标的元素
llen key //获取列表的⻓度
lpop key // 从列表左侧弹出元素
rpop key // 从列表右侧弹出元素
lrem key count value //从列表中找到等于value的元素,并进⾏删除,根据count的不同有不同的情
况
lset key index newValue //修改指定索引下标的元素
blpop key timeout //阻塞式左弹出key
brpop key timeout //阻塞式右弹出key
3. 应用场景
 
(1) 消息队列
redis list 数据类型对于⼤部分使⽤者来说,是实现队列服务的最经济,最简单的方式。很多公司使用 redis 做消息队列, lpush + brpop rpop 命令,实现先进先出,如果消费失败客户端把 key 再放回去,消费成功 remove 掉。
 
(2) “ 最新内容
hexists key field //判断filed是否存在
hkeys key //获取所有的field
hvals key //获取所有的value
hgetall key //获取所有的field-value ,如果元素数较多会存在阻塞redis的可能
hincreby key filed
rpush key value [value...] //从右插⼊元素
lpush key value [value...] //从左边插⼊元素
lrange key start end //获取指定范围的元素列表
lindex key index //获取列表指定索引下标的元素
llen key //获取列表的⻓度
lpop key // 从列表左侧弹出元素
rpop key // 从列表右侧弹出元素
lrem key count value //从列表中找到等于value的元素,并进⾏删除,根据count的不同有不同的情
况
lset key index newValue //修改指定索引下标的元素
blpop key timeout //阻塞式左弹出key
brpop key timeout //阻塞式右弹出key因为 list 结构的数据查询两端附近的数据性能⾮常好,所以适合⼀些需要获取最新数据的场景,⽐如新
闻类应⽤的 “最近新闻”。

4.优化建议

(1) list 是链表结构,所有如果在头部和尾部插⼊数据,性能会⾮常⾼,不受链表⻓度的影响;但如果在链表中插⼊数据,性能就会越来越差。
 
5. 常用组合:
lpush + lpop =
lpush + rpop = 队列
lpush + ltrim = 有限集合
lpush + brpop = 消息队列
 
 
六、 set 数据类型的应⽤场景
 
1. 简介
set 数据类型是⼀个集合(没有排序,不重复),可以对 set 类型的数据进⾏添加、删除、判断是否 存在等操作(时间复杂度是 O(1) )   
set 集合不允许数据重复,如果添加的数据在 set 中已经存在, 将只保留⼀份。   
set 类型提供了多个 set 之间的聚合运算,如求交、并、差集,这些操作在 redis 部完成,效率很⾼。
 
2. 数据模型
 
 
sadd key value [value...] //添加元素
srem key value [value...] //删除元素
scard key //计算元素的个数
sismember key value //判断元素是否在集合中
srandmember key [count] //随机从集合中返回指定个数的元素,不写默认为1
spop key //从集合随机取出元素
smembers key //获取集合内的所有元素
sinter key1 key2 //求集合的交集
sunion key1 key2 //求集合的并集
sdiff key1 key2 //求集合的差集
3. 应⽤场景
set 类型的特点是 —— 不重复且⽆序的⼀组数据,并且具有丰富的计算功能,在⼀些特定的场景中可以高效的解决⼀般关系型数据库不⽅便做的⼯作。
 
(1)“ 共同好友列表
社交类应用中,获取两个⼈或多个⼈的共同好友,两个⼈或多个⼈共同关注的微博这样类似的功 能,⽤ MySQL 的话操作很复杂,可以把每个人的好友 id 存到集合中,获取共同好友的操作就可以简单 到⼀个取交集的命令就搞定。
 
// 这⾥为了⽅便阅读,把 id 替换成姓名
sadd user:wade james melo paul kobe
sadd user:james wade melo paul kobe
sadd user:paul wade james melo kobe
sadd user:melo wade james paul kobe
// 获取 wade 和 james 的共同好友
sinter user:wade user:james
/* 输出:
 * 1) "kobe"
 * 2) "paul"
 * 3) "melo"
 */
 // 获取⾹蕉四兄弟的共同好友
 sinter user:wade user:james user:paul user:melo
 /* 输出:
 * 1) "kobe"
 */
类似的需求还有很多 , 必须把每个标签下的⽂章 id 存到集合中,可以很容易的求出几个不同标签下的共同⽂章; 把每个⼈的爱好存到集合中,可以很容易的求出几个人的共同爱好。
 
(2) 唯⼀ ip
跟踪⼀些具有唯⼀性的⼀些数据,比如访问某⼀博客的唯⼀ ip 地址的信息,我们仅需要在每次访问的时候,将 ip 存入 redis 中。利用服务器端聚合操作⽅便⾼效的特性,维护数据对象之间的关联关系。
 
七、 sorted set 数据类型的应⽤场景
 
1. 简介
set 的基础上给集合中每个元素关联了⼀个分数,往有序集合中插⼊数据时会自动根据这个分数 排序。它保留了元素不能重复的特性,并且元素是有序的。
2. 基本操作
 
zadd key score member //score是可以重复的,添加key的时候指定分数
zcard key //计算成员个数
zscore key member //计算某个成员的分数
zrank key member //计算成员排名,从低到⾼
zrevrank key member //计算成员排名,从⾼到低
zrem key member [member...] //删除成员
zincrby key increnment member //增加成员的分数
zrange key start end [withscores] //从低到⾼返回指定排名的分数
zrevrange key start end [withscores] //从⾼到低返回
zrangebyscore key min max [withscores] [limit offset count] //按照分数从低到⾼返回
zrevrange score key min max [withscores] [limit offset count] //按照分数从⾼到低返回成员
withscore 代表返回的时候带上成员的分数 。
还有求交集,并集等操作。
 
3. 应⽤场景
在集合类型的场景上加入排序就是有序集合的应用场景了。
 
(1) 根据好友的 亲密度 排序显示好友列表。
// ⽤元素的分数(score)表示与好友的亲密度
zadd user:kobe 80 james 90 wade 85 melo 90 paul
// 根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
/**
 * 输出:
 * 1) "wade"
 * 2) "paul"
 * 3) "melo"
 * 4) "james"
 */
// 增加好友的亲密度
zincrby user:kobe 15 james
// 再次根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
/**
 * 输出:
 * 1) "james"
 * 2) "wade"
 * 3) "paul"
 * 2) "melo"
 */
类似的需求还出现在根据文章的阅读量或点赞量对文章列表排序。
 
(2)排
 
实效性
 
从排行榜的实效性上划分,主要分为:
实时榜:基于当前⼀段时间内数据的实时更新,进⾏排行。例如:当前一小时内游戏热度实时 榜,当前一小时内明星送花实时榜等
历史榜:基于历史⼀段周期内的数据,进行排行。例如:日榜(今天看昨天的),周榜(上⼀周的),月榜(上个月的),年榜(上⼀年的)
 
业务数据类型
 
从需要排⾏的数据类型上划分,主要分为:
单类型数据排⾏榜:是指需要排行的主体不需要区分类型,例如,所有⽤户积分排⾏,所有公贡献值排⾏,所有游戏热度排⾏等
多类型(复合类型)数据排行榜:是指需要排行的主体在排行中要求有类型上的区分,例如:竞技类游戏热度排⾏、体育类游戏热度排⾏、MOBA类游戏操作性排⾏、⻆⾊/ 回合 / 卡牌三类游戏热
度排⾏等
 
展示唯度
 
从榜单的最终展示唯度上划分,主要分为:
单唯度:是指选择展示的排行榜就是基于⼀个唯度下的排行,例如前面提到的游戏操作性排行榜,就仅展示所有MOBA 类游戏按操作性的评分排行
多唯度:是指选择展示的排行榜还有多种唯度供⽤户选择,仍然以前面的 游戏排行为例,唯度除了操作性,还有音效评分排行,难易度评分排行,画面评分排行等。
 
展示数据量
 
从需要展示的数据量上划分,主要分为:
topN 数据:只要求展示 topN 条排行纪录,例如:最火 游戏 top20
全量数据:要求展示所有数
 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值