Redis 应用场景

Redis应用场景

缓存

作为Key-Value形态的内存数据库,Redis最先会被想到的应用场景便是作为数据缓存。而使用Redis缓存数据非常简单,只需要通过String类型将序列化后的对象存起来即可,不过也有一些注意的地方。

  • 必须保证不同对象的key不会重复,并且使key尽量短,使用使用类名(表名)加主键拼接而成。
  • 选择一个优秀的序列化方式也很重要,目的是提高序列化的效率和减少内存占用。
  • 缓存内容与数据库的一致性,这里一般有两种做法:
    1. 只在数据库查询后将对象放入缓存,如果对象发生了修改或删除操作,直接清除对应缓存(或设为过期)
    2. 在数据库新增和查询后将对象放入缓存,修改后更新缓存,删除后清除对应缓存(或设为过期)。
127.0.0.1:6379> set CACHE_KEY cacheData #新增
OK
127.0.0.1:6379> set CACHE_KEY updataCacheData #修改
OK
127.0.0.1:6379> get CACHE_KEY
"updataCacheData"
127.0.0.1:6379> expire CACHE_KEY 1  #设置1秒后过期
(integer) 1
127.0.0.1:6379> ttl CACHE_KEY #查看还有多少时间过期 -1永不过期,-2过期
(integer) -2
127.0.0.1:6379> del CACHE_KEY #删除
(integer) 0
127.0.0.1:6379> exists CACHE_KEY #是否存在
(integer) 0
127.0.0.1:6379> 
消息队列

Redis中的list的数据结构实现是双向链表,所以可以非常便捷的应用于消息队列(生产者/消费者模型)。消息的生产者只需要通过lpush将消息放入list,消费者可以通过rpop取出该消息,并且可以保证消息的有序性。如果需要实现带有优先级的消息队列也可以选择sorted set。 而pub/sub功能也可以用作发布者/订阅者模型的消息。无论使用何种方式,由于Redis用于持久化功能,也不需要担心由于服务器故障导致消息丢失的情况。

127.0.0.1:6379> lpush QUEUE_KEY queueV01 queueV02 queueV03 #生产者(放入)
(integer) 3
127.0.0.1:6379> rpop QUEUE_KEY  #消费者 (取出)
"queueV01"
127.0.0.1:6379> rpop QUEUE_KEY 
"queueV02"
127.0.0.1:6379> rpop QUEUE_KEY 
"queueV03"
127.0.0.1:6379> rpop QUEUE_KEY 
(nil)
127.0.0.1:6379> 

================
#Zset(sorted set)带有优先级的消息的队列

127.0.0.1:6379> zadd ZQUEUE_KEY 60 v1 70 v2 80 v3 90 v4 #zset 是使用score来设置优先级的
(integer) 4
127.0.0.1:6379> zrange ZQUEUE_KEY 0 -1 
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> zrange ZQUEUE_KEY 0 -1  withscores
1) "v1"
2) "60"
3) "v2"
4) "70"
5) "v3"
6) "80"
7) "v4"
8) "90"
127.0.0.1:6379> zrangebyscore ZQUEUE_KEY 60 90
1) "v1"
2) "v2"
3) "v3"
4) "v4"
时间轴(Timeline)

list作为双向链表,不光可以作为队列使用。如果将它用做栈便可以成为一个公用的时间轴。当用户发完微博后,都通过lpush将它存放在一个key为LAST_WEIBO 的list中,之后便可以通过lrange取出当前最新的微博。

127.0.0.1:6379> lpush LAST_WEIBO wb1 wb2 wb3 wb4 wb5
(integer) 5
127.0.0.1:6379> lrange LAST_WEIBO 2 4
1) "wb3"
2) "wb2"
3) "wb1"
127.0.0.1:6379> lrange LAST_WEIBO 0 -1
1) "wb5"
2) "wb4"
3) "wb3"
4) "wb2"
5) "wb1"
排行榜

使用sorted set 和一个计算热度的算法便可以轻松打造一个热度排行榜,zrevrangebyscore可以得到以分数倒序排列的序列,zrank可以得到一个成员在该排行榜的位置(是分数正序排列时的位置,如果要获取倒序排列时的位置需要用zcard-zrank)。

计数器

计数功能应该是最适合Redis的使用场景之一了,因为它高频率读写的特征可以完全发挥Redis作为内存数据库的高效。在Redis的数据结构中,Stringhashsorted set 都提供了incr方法用于原子性的自增操作,下面举例说明一下它们各自的使用场景:

  • 如果应用需要显示每天的注册用户数,便可以使用string作为计数器,设定一个名为REGISTERED_COUNT_TODAY的key,并在初始化时给它设置一个到凌晨0点的过期时间,每当用户注册成功后便使用incr命令使该key增长1,同时当每天凌晨0点后这个计数器都会因为key过期使值清零。
  • 每条微博都有点赞数、评论数、转发数和浏览数四条属性,这时用hash进行计数会更好,将该计数器的key设为weibo:weibo_id,hash的field为like_number、comment_number、forward_number 和view_number,在对应操作后通过hincrby使hash中的field自增。
127.0.0.1:6379> hset weibo weibo_id 111111
(integer) 1
127.0.0.1:6379> hget weibo weibo_id
"111111"
127.0.0.1:6379> hmset 111111 like_number 23 comment_number 46 forward_number 14 view_number 96
OK
127.0.0.1:6379> hkeys 111111
1) "like_number"
2) "comment_number"
3) "forward_number"
4) "view_number"
127.0.0.1:6379> hincrby 111111 like_number 1
(integer) 24
127.0.0.1:6379> hmget 111111 like_number comment_number forward_number view_number
1) "24"
2) "46"
3) "14"
4) "96"
127.0.0.1:6379> hincrby 111111 comment_number 3
(integer) 49
127.0.0.1:6379> hmget 111111 like_number comment_number forward_number view_number
1) "24"
2) "49"
3) "14"
4) "96"
127.0.0.1:6379>
  • 如果应用有一个发帖排行榜的功能,便选择sorted set 吧,将集合的key设为POST_RANK。当用户发帖后,使用zincrby将该用户id的score增长1. **sorted set **会重新进行排序,用户所在排行榜的位置也就会得到实时的更新。
好友关系

新浪微博Redis应用分享中使用的,微博的Redis主要是用在计数和好友关系两方面,《Redis设计与实现》中作者最开始就是希望set解决传统数据库无法快速计算集合中交集这个功能。 scienjus博主猜测说: 对于一个用户A,将它的关注和粉丝的用户id都存放至两个set中:

  • A:follow :存放A所有关注的用户id
  • A:follower : 存放A所有粉丝的用户id 那么通过sinter命令可以根据A:followA:follower的交集得到与A相互关注的用户。当A进入另一个用户B的主要后,A:followB:follow 的交集便是A和B的共同专注,A:followB:follower 的交集便是A关注的人也关注了B。

friends

127.0.0.1:6379> sadd A_FOLLOWER C E F
(integer) 3
127.0.0.1:6379> SADD A_FOLLOW B C D
(integer) 3
127.0.0.1:6379> SADD B_FOLLOWER A C F 
(integer) 3
127.0.0.1:6379> SADD B_FOLLOW C D
(integer) 2
127.0.0.1:6379> SINTER A_FOLLOW A_FOLLOWER
1) "C"
127.0.0.1:6379> SINTER A_FOLLOW B_FOLLOW
1) "D"
2) "C"
127.0.0.1:6379> SINTER A_FOLLOW B_FOLLOWER
1) "C"
127.0.0.1:6379>
分布式锁

在Redis 2.6.12版本开始,Stringset命令增加了三个参数:

  • EX : 设置键的过期时间(单位为秒)
  • PX : 设置键的过期时间(单位为毫秒)
  • NX | XX :当设置为 NX 时,仅当key存在时才进行操作,设置为XX时,仅当key不存在才会进行操作。 由于这个操作是原子性的,可以简单地以此实现一个分布式锁,例如: **set key "lock" EX 1 XX 如果这个操作返回false, 说明key的添加不成功,说明key的添加不成功,也就是当前有人在占用这把锁。而如果返回true,则说明得了锁,便可以继续操作 ,并且在操作后通过del命令释放掉锁。并且即使程序因为某些原因并没有释放锁,由于设置了过期时间,该锁也会在1秒后自动释放,不会影响到其他程序的运行。
倒排索引

倒排索引是构造搜索功能的最常见的方式,在Redis中也可以通过set进行建立倒排索引,这里以简单的拼音+前缀搜索城市功能举例: 假设一个城市 北京,通过拼音词库将北京转为beijing,再通过前缀分词将这两个词分为若干个前缀索引,有:北、北京、b、be…beijin和beijing。将这些索引分别作为set的key(例如:index:北)并存储北京的id,倒排索引便建立好了。接下来只需要在搜索时通过关键词取出对应的set并得到其中的id即可

一些建议
  • Redis速度快是建立在内存数据库基础上的,但是一台服务器的内存要比磁盘金贵许多,所以在项目初期不要想什么都往Redis里放,这样当数据量上来后很快内存就会不够用,反而得不偿失。合理的利用有限的内存,将读(写)频繁的热数据放在Redis中才能更好感受到它带来的性能提升。

  • Redis虽然提供了RDB和AOF两种持久化方式,但是普遍还是认为Redis的持久化并不是很靠谱。这也是我一直不敢尝试彻底的用Redis去实现第五点(好友关系)的原因。

  • 虽然Redis在3.0之后才推出官方的集群方案,但是也有很多不错的开源方案,比如Codis。

转自http://www.scienjus.com/redis-use-case/

转载于:https://my.oschina.net/ddyblackhat/blog/683684

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值