redis-4.redis的消息订阅、pipeline、事务、modules、布隆过滤器、缓存LRU

redis

pipeline

啤酒理论,比如商店有24瓶啤酒,你总不能拿一瓶回家喝一瓶,你要找个箱子一起把啤酒搬回家
buffer 机制也可以这样子理解,避免了来回调用

在这里插入图片描述

一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。
Redis很早就支持管道(pipelining)技术,因此无论你运行的是什么版本,你都可以使用管道(pipelining)操作Redis。

redis 的冷启动可以通过他预先加载

[root@admin vmuser]# nc localhost 16379
keys *
-NOAUTH Authentication required.
auth 123456
+OK
keys *
*0
set k1 hello

这个时候登录redis-cli

127.0.0.1:16379> get k1
"hello"
127.0.0.1:16379> 

使用管道将redis值插入,\n 作为分割
下面的 $3 的意思是 宽度为3 是100

[root@admin vmuser]# echo -e "auth 123456\n set k2 99\n incr k2\n get k2" | nc localhost 16379
+OK
+OK
:100
$3
100

Pub/Sub 发布订阅

help @pubsub

  PSUBSCRIBE pattern [pattern ...]
  summary: Listen for messages published to channels matching the given patterns
  since: 2.0.0

  PUBLISH channel message
  summary: Post a message to a channel
  since: 2.0.0

  PUBSUB subcommand [argument [argument ...]]
  summary: Inspect the state of the Pub/Sub subsystem
  since: 2.8.0

  PUNSUBSCRIBE [pattern [pattern ...]]
  summary: Stop listening for messages posted to channels matching the given patterns
  since: 2.0.0

  SUBSCRIBE channel [channel ...]
  summary: Listen for messages published to the given channels
  since: 2.0.0

  UNSUBSCRIBE [channel [channel ...]]
  summary: Stop listening for messages posted to the given channels
  since: 2.0.0

服务端

127.0.0.1:16379> PUBLISH ooxx hello
(integer) 0

客户端

127.0.0.1:16379> SUBSCRIBE ooxx
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ooxx"
3) (integer) 1

这个时候客户端是获取不到数据的,需要服务端重新执行publish,客户端一直保持才能获取服务端数据

如果你要想看到之前的记录呢,如果插入数据库,在从数据库查,每个人查的话就会变得非常大的消耗

在这里插入图片描述

可以这样子使用,但是这种架构模型如果出现client1 去PUBLISH client2 没有收到,但是sorted set 收到该消息并缓存怎么办?

解决方案:启动不同的redis去接收订阅的消息,有的用来推送给用户,有的用来发给kafka,继而存储到数据库中,大家一起消费

在这里插入图片描述

事务

redis 的事务其实很简单,没有mysql 那么复杂,因为作者设计初衷就是为了快速读取

help @transactions

  DISCARD -
  summary: Discard all commands issued after MULTI
  since: 2.0.0

  EXEC -
  summary: Execute all commands issued after MULTI
  since: 1.2.0

  MULTI -
  summary: Mark the start of a transaction block
  since: 1.2.0

  UNWATCH -
  summary: Forget about all watched keys
  since: 2.2.0

  WATCH key [key ...]
  summary: Watch the given keys to determine execution of the MULTI/EXEC block
  since: 2.2.0

首先最初概念是 redis 是单进程的,如果client1,client2 同时发起了事务,这个时候该如何处理
client1 为绿色
client2 为黄色
在这里插入图片描述
如果黄色 client2 的exec 最先到达redis ,那么首先执行 client2,在执行client1,谁的exec 先到达,就先执行谁的

添加一个watch使用,如果redis的key已经发生改变,后面的操作将不在执行,例如client1 的get key 将不再操作
在这里插入图片描述

              开启事务
127.0.0.1:16379> MULTI
OK
127.0.0.1:16379(TX)> set k1 aaa
QUEUED
127.0.0.1:16379(TX)> set k2 bbb
QUEUED
              提交
127.0.0.1:16379(TX)> exec
1) OK
2) OK

client1 首先开启事务,但是提交exec 在client2 后面,这个时候就获取为null

127.0.0.1:16379> MULTI
OK
127.0.0.1:16379(TX)> get k1
QUEUED
127.0.0.1:16379(TX)> exec
1) (nil)

client2 最后开启事务,提前提交exec

127.0.0.1:16379> MULTI
OK
127.0.0.1:16379(TX)> del k1
QUEUED
127.0.0.1:16379(TX)> exec
1) (integer) 1
127.0.0.1:16379> 

WATCH

client 1 事务以下不在操作,所以是nil

127.0.0.1:16379> WATCH k1
OK
127.0.0.1:16379> MULTI
OK
127.0.0.1:16379(TX)> get k1
QUEUED
127.0.0.1:16379(TX)> keys * 
QUEUED
127.0.0.1:16379(TX)> exec
(nil)
127.0.0.1:16379> MULTI
OK
127.0.0.1:16379(TX)> keys *
QUEUED
127.0.0.1:16379(TX)> set k1 sdfsfds
QUEUED
127.0.0.1:16379(TX)> exec
1) (empty array)
2) OK
127.0.0.1:16379> get k1
"sdfsfds"

为什么 Redis 不支持回滚(roll back)

如果你有使用关系式数据库的经验, 那么 “Redis 在事务失败时不进行回滚,而是继续执行余下的命令”这种做法可能会让你觉得有点奇怪。
以下是这种做法的优点:
Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
有种观点认为 Redis 处理事务的做法会产生 bug , 然而需要注意的是, 在通常情况下, 回滚并不能解决编程错误带来的问题。 举个例子, 如果你本来想通过 INCR 命令将键的值加上 1 , 却不小心加上了 2 , 又或者对错误类型的键执行了 INCR , 回滚是没有办法处理这些情况的。

modules

类似游戏别人出来的mode,可以拿来玩
在这里插入图片描述

点进去,redis 比较火热的 bloom就在这里面

RedisBloom-布隆过滤器

点小房子进说明

在这里插入图片描述

地址:https://github.com/RedisBloom/RedisBloom

下载布隆过滤器

   wget https://github.com/RedisBloom/RedisBloom/archive/refs/heads/master.zip

解压安装

   unzip master.zip 

在这里插入图片描述
在这里插入图片描述

这个里面也有一个makefile,使用make命令安装,首先要有gcc
使用make 命令
这里肯定有人会报错的

 error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (size_t ii = 2; ii < argc; ++ii) {
 
 error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (int ii = 0; ii < argc; ii += 2) {
     ^
make: *** [/home/vmuser/bf/RedisBloom-master/src/rebloom.o] Error 1

报错因为是我们这个时候装的是最新布隆过滤器的版本,而我们Linux主机的gcc 版本确跟他最新的版本不吻合,需要使用c99
在这里插入图片描述

报错解决方案
  1. 降低过滤器版本
    在这里插入图片描述
    链接地址:https://blog.csdn.net/linkedin_36542996/article/details/119384031
  2. 升级gcc
    在这里插入图片描述 链接地址:https://blog.csdn.net/weixin_40836179/article/details/108245436

这里博主使用的方案2
但是!又出问题

/home/RedisBloom-master/src/rm_tdigest.c:19:10: fatal error: tdigest.h: No such file or directory
   19 | #include "tdigest.h"
      |          ^~~~~~~~~~~
compilation terminated.
make: *** [/home/vmuser/bf/RedisBloom-master/src/rm_tdigest.o] Error 1

解决办法参考链接
1.https://blog.csdn.net/weixin_49383182/article/details/117969587
2.https://blog.csdn.net/qq_42816268/article/details/117332771
在这里插入图片描述
nmd,一个工具这么费劲,博主直接切换方案了,非常赞同方案1的兄弟

删除之前操作,重新下载

wget https://github.com/RedisBloom/RedisBloom/archive/refs/tags/v2.2.12.zip

解压获得
在这里插入图片描述

执行make 命令,获得我们钦慕已久的 redisbloom.so ,tm

在这里插入图片描述

复制移动

 cp redisbloom.so /opt/redis6/

重新启动redis

加载模块 redisbloom,一定要使用绝对路径

[root@admin redis6]   service redis_6379 start  --loadmodule /home/bf/RedisBloom-2.2.12/redisbloom.so 

修改6379 配置文件
在这里插入图片描述
布隆过滤器:用小空间解决大量数据匹配的问题
在这里插入图片描述
在这里插入图片描述

redis作为缓存与数据库的区别
在这里插入图片描述
在这里插入图片描述

缓存LRU

在redis中设置内存maxmemory有以下这几种模式
· 在自己conf配置文件中可以找到
在这里插入图片描述

回收策略
当maxmemory限制达到的时候Redis会使用的行为由 Redis的maxmemory-policy配置指令来进行配置。
以下的策略是可用的:
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
选择正确的回收策略是非常重要的,这取决于你的应用的访问模式,不过你可以在运行时进行相关的策略调整,并且监控缓存命中率和没命中的次数,通过RedisINFO命令输出以便调优。
一般的经验规则:
使用allkeys-lru策略:当你希望你的请求符合一个幂定律分布,也就是说,你希望部分的子集元素将比其它其它元素被访问的更多。如果你不确定选择什么,这是个很好的选择。.
使用allkeys-random:如果你是循环访问,所有的键被连续的扫描,或者你希望请求分布正常(所有元素被访问的概率都差不多)。
使用volatile-ttl:如果你想要通过创建缓存对象时设置TTL值,来决定哪些对象应该被过期。
allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。
为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效,因为没有必要为键取设置过期时间当内存有压力时。

reids面试题 会随着访问延长?不对
1,会随着访问延长?不对
2,发生写,会剔除过期时间
3,倒计时,且,redis不能延长

127.0.0.1:16379> set k1 aaa ex 20
OK
127.0.0.1:16379> ttl k1
(integer) 17
127.0.0.1:16379> ttl k1
(integer) 16
127.0.0.1:16379> ttl k1
(integer) 15
127.0.0.1:16379> ttl k1
(integer) 3
127.0.0.1:16379> ttl k1
(integer) 2
127.0.0.1:16379> ttl k1
(integer) -2
127.0.0.1:16379> get k1 
(nil)
127.0.0.1:16379> ttl k1
(integer) -1
127.0.0.1:16379> EXPIRE k1 20
(integer) 1
127.0.0.1:16379> ttl k1
(integer) 19
127.0.0.1:16379> ttl k1
(integer) 18

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值