redis学习四redis消息订阅、pipeline、事务、modules、布隆过滤器、缓存LRU
管道
参考链接: http://redis.cn/topics/pipelining.html
可以将多个命令通过一次连接处理,这让通信的成本变低了。
首先yum install nc
nc localhost 6380 建立socket通信
redis 发布订阅
参考链接:http://redis.cn/topics/pubsub.html
publish 向通道推送消息
应用如下:
此时发现是没有消息到ooxx这个通道的【注意这里只能是我消费端监听到以后,往通道里面推送的消息
消费端才能收到】
此时处于监听状态,再推一条消息过去:
另一边的消费者马上能接收到推送的这条testhello的消息
但是我们微信、QQ那些也能够查到历史的消息,那么这些消息是放在哪去存呢?
如果是数据库里面的话,数据全量可以保证,但是多人查询的时候,成本比较高。
所以采用redis来存:
1、我们把消息分为实时性的和历史性的
2、历史性的数据又分为三天内的和更老的数据【全量数据肯定都是在数据库里面】
3、对于最近的数据采用redis缓存(【主要解决数据的读请求(很快)】)
4、实时性的数据则通过发布订阅来解决
5、对于三天内的数据则可以通过sorted_set来根据他发送的时间
来做排序(可以通过ZREMRANGEBYRANK KEY START STOP来进行删除)【注意:
scores是时间,k,v是你设计的,比如key是谁发送的+type,value是msg文本内容或者是图片声音的url
】
6、通过另一个客户端处理数据的发布订阅,让数据实时,然后再将过去3天的数据同步到redis
的sorted_set,然后再通过kafka将数据慢慢的同步到数据库。
当然还有一种方案:
首先通过一个客户端pub发送命令到redis,然后redis再通过sub发送订阅消息到另一个
客户端,然后再通过sub命令将命令发送到redis自己的一个订阅里面(存入zset),再通过sub发送订阅消息
到一个微服务中(service),再通过这个service给kafka发送消息,再到数据库服务层接收消息,存入
消息到数据库(订阅消息到了直接通过sub广播出去)
redis事务处理
参考链接:http://redis.cn/topics/transactions.html
multi:标记开启事务
exec:按顺序执行所有的命令(出现错误回滚撤销)
discard:取消事务
watch:相当于乐观锁【在事务执行之前监控某些key,
如果发现key所对应的value被更改了直接撤销事务,不执行】
如果是多个客户端操作同一个数据,并且开启事务
1、client1先开启事务,
2、然后client2开启事务
3、client2要删除k1
4、client1要查询k1
5、client2执行事务
6、client1执行事务
优先出现exec的事务关联的指令优先执行(上图则先执行2的所有事务)1的事务会直接返回空
下面来演示:
下面再来模拟两个客户端开启事务的情况:客户端1和客户端2分别发起一个事务
客户端1get一个k1
客户端2删除一个k1
客户端1再取出这个k1
这时返回的是一个空的。
下面来演示watch命令:
客户端1执行watch命令监听这个k1是否发生变化
然后通过客户端2去修改这个k1的value
最后在客户端1执行这个事务:
返回的是个nil表明客户端1的事务未被执行【一般用于幂等的处理】
REDIS BIOOM
首先在官方文档找到布隆过滤器插件相关:
进入到github的这个页面: https://github.com/RedisBloom/RedisBloom
再解压安装包,解压后执行make命令会出现一个redisbloom.so文件,这是一个redisbloom的扩展库。
copy到我redis的目录下:
再运行执行我们的redisbloom的扩展库。
进入6379端口的redis就能看到有相关的bf命令了
包含布隆过滤器,counting bloom,布谷鸟过滤器
通过bloom过滤器解决缓存穿透
不能让本来就没有的东西,查询访问到数据库上面去,这里就需要布隆过滤器解决这个问题。【用小的空间解决大量数据的问题】
首先我们准备一个bitmap来存我们的元素
假设一个元素经过三个映射函数,将bitmap对应的位置标记为1
加入此刻再来一个元素2,然后存在调用映射函数与元素一的bitmap中存的某些位重叠了。
此时再来一个元素三,元素三在数据库里面是没有的,但是它的映射函数刚好覆盖到元素1和元素2对应的bitmap中的位置,这时就会有一定概率造成不存在的数也落在bitmap上面判断数据成功了,就会直接去从数据库里面查
如果redis是个原生的东西,不带bloom的模块
则可以通过客户端实现布隆算法,自己承载bitmap
也可以客户端只有布隆算法,bitmapredis存
要么就redis集成布隆的模块
既然不能百分百避免穿透,那么我们的优化策略是:
1、穿透了,不存在
2、client,增加redis中的key,value标记(标记查询的不存在)
3、数据库增加了元素,必须要完成元素对bloom的添加
redis作为数据库/缓存的区别
作为数据库:
缓存的数据不重要,并且不是全量的数据,缓存应该随着访问变化【所以存入的是热数据】。
作为缓存:
redis里的数据怎么能随着业务变化只保留热数据,因为内存大小是有限制的。
key的有效期
首先key的有效期是由业务逻辑以及业务运转来推动的
在当前key已经在倒计时的过程中,如果修改key对应的value,会直接剔除过期时间
要靠自己的操作去延长
如上操作则是定时,指定过期时间
LFU: 强调的是使用了多少次
LRU:强调的是多久没使用了
过期策略的选型:
volatiel-ttl:比较的是时间成本,复杂度比较高
allkeys-lru:没怎么去过期的,然后靠redis自己提出空间,使用这个。
volatile-lru:缓存里面大量的数据到期,优先使用。