2021.7.19笔记

Redis管道
举个例子就是你要喝20瓶酒,你是去超市买1瓶,回家喝完,然后再去超市买一瓶,再回家喝,还是全都买回去,回家一瓶一瓶喝,肯定是第二种,因为省事,管道的概念就是这个,通过管道你可以一次运行很多命令。
首先yum install nc下载Navicat
然后nc localhost 6379建立和6379这个redis端口的链接
这个时候输入命令比如 set k1 hello,到redis客户端会发现生成了k1这个元素,也就是说哪怕你没有redis客户端,只要能和redis建立一个socket链接,然后输入相应的命令也是可以执行的
这时候用echo -e “set k2 99\n incr k2\n get k2” | nc localhost 6379通过管道的方式交给nc 这就是管道,一次性发送多个命令,减少通信成本

Redis发布订阅
PSUBSCRIBE pattern [pattern …] 订阅一个或多个符合给定模式的频道
2 PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态
3 PUBLISH channel message 将消息发送到指定的频道
4 PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道
5 SUBSCRIBE channel [channel …] 订阅给定的一个或多个频道的信息
6 UNSUBSCRIBE [channel [channel …]] 指退订给定的频道

运行publish ooxx hello指令,向ooxx这个频道(不是管道,别弄混了)发送hello,然后用另一个客户端链接相同端口的redis,用subscribe ooxx指令查看ooxx这个频道的信息,发现没有刚才输入的hello,切回去再发送一句话,然后切回来发现可以看到了,也就是说只能看到订阅频道之后的内容,这时候想一个问题,像微信群qq群都是支持查找历史记录的,那这些记录都是放到哪里的呢,是redis里还是mysql数据库里?如果放到mysql数据库,数据的全量可以得到保障,但是无数的用户进行查询的时候成本就太高了,具体怎么做,我们往下看
首先有两个需求,第一个要看实时的消息,第二个看历史消息
历史消息也分几分钟前,几天前,几个月前的或者更老的,这里我们要知道大部分的人是不会查找那么老的记录的(除非是忘了女朋友说过的话),只有少数人偶尔会查一些老数据,然后要弄清楚redis和mysql的具体作用,数据全量肯定是要存在mysql里的,因为空间大,但是查询成本高,如果所有用户不管是几天前的还是几年前的都是从mysql数据库里去查,那mysql的压力就太大了,这时候就要选择用redis来当缓存,缓存的目的大部分场景是解决数据的读请求,因为redis就一个特点就是快,接下来就要分工,首先实时的聊天内容就可以用到redis的发布订阅功能就可以解决,那近一段时间的历史数据和更老的历史数据放哪里,更老的肯定是放mysql里,因为查询量很少,那近段时间的历史数据放哪里,之前讲了sorted set数据类型,有序的集合,因为聊天内容肯定得有序的,但是redis只是作为一个缓存来使用就不需要全量数据,redis也没有那么大的空间,那就要设定一个时间,比如5天内的历史记录放到redis里来缓存,更老的数据就要删除掉,可以用zremrangebyrank,zremrangebyscore这两个指令,一个是根据score值删除,一个是根据排名来删除,因为redis里面是从小到大排列的,那我们只需要把日期小的删除就行,把时间作为记录的分值,1号分值为1,二号分值为2,以此类推,把消息作为元素,然后zremrangebyscore 给出一个分值区间,把这个区间的所有数据删除,细节说完了来看看具体的架构是什么,
首先实时数据发送到redis消息订阅里,其他用户可以看到内容,然后再用另一个redis的zset来存储发送的数据作为短期历史数据,然后再部署另外的微服务service获取数据导到kafka,然后dbservice去消费,然后链接mysql数据库。
redis事务
redis的事务不像mysql的那样完整,redis的特征就是快
因为redis是单进程的,不同的客户端用multi命令开启事务,然后是一大堆命令,最后谁先exec,谁先运行,运行结束,轮到下一个客户端,不会互相阻碍。
还可以用watch监听元素,如果发现元素发生改变,事务就不会开启,举个例子,watch k1 然后multi开启事务,get k1 ,这时候其他客户端set k1 xxxx把k1改了,并且先exec了,这时候k1已经被更改了,你再exec事务也不会运行了。
布隆过滤器
先下载布隆过滤器到linux上,然后解压包,然后make,然后把so文件拷贝到redis包里,然后启动 redis-server --loadmodule /xx/xx/xx/redisbloom.so
启动成功之后在6379端口多了几个bf的命令,可以再开一个6380的端口,测试一下是没有bf命令的。
布隆过滤器可以解决缓存穿透问题
当你要查询一个数据的时候肯定先访问缓存,缓存里没有再访问数据库,那如果这个数据在数据库里也不存在,那数据库就要做很多无用功,假如有人利用这一点不断地向数据库查找这个数据,数据库就白白的建立连接,请求,搜索,所以这时候就需要一个过滤器,把数据库里有的东西都放到一个集合里,当你查询的时候如果在集合里找到了就直接返回,如果没找到也不需要去数据库里了,这时候就是一个空间问题了,如何能把庞大的数据放到内存里,这就是布隆过滤器要解决的问题,利用的是bitmap,二进制位位图,如果能用二进制位的话那占用的空间就很小,原理很简单,就是把一个元素经历N个映射函数,经过每一个映射函数的处理都会得到一个数,然后把相对应位置的二进制位的数值从0变成1,然后在你查询数据的时候也会经过这些映射函数,如果被映射函数处理完发现所对应的二进制位不全都是1,那就代表没有这个数据,如果全都是一也不能代表一定有,因为这个方法是有几率出错的,当你查询某一个数据的时候,经过映射处理,可能发现该位置都是1,但其实那是很多个不同数据分别修改的,并不是一个数据修改的,但是几率很低小于百分之一,还是那个观点redis强大就强大在速度快,拿稍微一点的复杂度,一点损耗来换时间成本,用极小的的概率换取大量的减少穿透,且成本低,我们来想三种情况
第一种:客户端自己实现布隆算法自己承载bitmap,redis只做缓存
第二种:客户端只有算法 redis 做bitmap和缓存
第三种:客户端什么都不做 redis集成
就算所有东西都压到redis上redis对cpu的损耗也不大,用第三种可以让客户端更轻量一些也更符合微服务的架构概念
redis作为数据库和缓存的区别
缓存数据“不重要”,缓存不是全量数据,缓存应该随着访问变化,应该放更多的热数据,我们现在只讨论redis作为缓存的功能,首先要解决的是redis的热数据的问题,因为内存的大小是有限的,也就是瓶颈,虽然速度快可以解决io的瓶颈,但是大小是redis的瓶颈
key的有效期
业务逻辑来推动key的有效期,业务需要这个key存在多久,key就存在多久
业务运转决定内存,内存是有限的,随着访问的变化应该淘汰冷数据,内存多大可以去配置文件设置maxmemory bytes 属性,如果内存满了可以看配置文件里maxmemory-policy noeviction属性,下面有一系列方法

noeviction: 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
volatile-lru: 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
volatile-ttl: 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl越小越优先被淘汰。
volatile-random: 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
allkeys-random: 跟上面一样,不过淘汰的策略是随机的 key。
volatile-lfu: Evict using approximated LFU among the keys with an expire set.(后面介绍)
allkeys-lfu: Evict any key using approximated LFU.(后面介绍)
volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。
LRU是最少使用(次数)
LFU是最长时间没用(时间间隔)

key的有效期如何设置
set k1 aaa ex 20,ex参数后面加上数字,多少秒后会过期。
时间有效期不会随着访问(get)而延长,但是会随着重写(set)而剔除有效期
expire命令也可以设置有效期 expire k1 50 50秒后过期
expireat k1 时间戳 ,指定某一时间过期

过期判定原理
Redis keys过期有两种方式:被动和主动方式。

当一些客户端尝试访问它时,key会被发现并主动的过期。

当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。

具体就是Redis每秒10次做的事情:

测试随机的20个keys进行相关过期检测。
删除所有已经过期的keys。
如果有多于25%的keys过期,重复步奏1.

这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值