4-------扩展篇

Stream

一个强大的支持多播的可持久化消息队列。

消息链表,将所有加入的信息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,重启内容还在的。

每个Stream都有唯一的名称,他就是Redis的key,在首次使用xdd指令追加消息时自动创建

  1. 每个Stream都挂有多个消费组,每个消费组都有一个last_delivered_id在stream数组之上往前移动,表示当前消费组已经在消费到了哪条信息。
  2. 每个消费组都有一个Stream内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup_create进行创建,并且初始化last_delivered_id变量。
  3. 同意消费组可以挂接多个消费者,这些消费者之间是竞争关系,任意一个消费者读取了信息都会移动游标
  4. 消费者内部有一个pending_ids,记录当前已经被客户端读取,但是还没有ack的消息。如果客户端没有ack,这个变量里面的消息ID就会越来越来多。

消息ID

消息ID形式:时间戳+本次时间内的第几条

1-2:当前时间为1毫秒,这个消息时这个时刻产生的第二条消息

消息内容

消息内容就是键值对,形如hash结构的键值对

增删改查

xadd:向Stream中追加消息

xdel:从Stream中删除消息

xrange:获取Stream中的消息列表

xlen:获取Stream消息长度

del:删除整个Stream消息列表中的所有信息

独立消费

客户端:xread block 1000 count 1 streams name

阻塞1s,如果有消息的话,就出来,没有的话就没用。

创建消费组

xgroup create name cg1 0-0;;;;没什么用的

消费

Stream消息太多怎么办

使用xadd指令删除掉。

消息如果忘记ack会怎样

不怎么样,PEL会越来越长

PEL如何避免丢失

反正保存在了PEL当中,等连接上了再传就行了。

Stream的高可用

可以在分布式集群中使用

分区Partition

Stream没有分区的能力,只能多创建几个Stream,并把不同的数据发送到不同的Stream上供消费

小结

感觉应该不会用到的,所以觉得没用

Info指令

获得Redis内部的一些参数

Server  服务器运行的环境参数
Clients 客户端相关信息
Memory 服务器运行内存统计数据
Persistence 持久化信息
Stats 通用统计数据
Replication 主从复制相关信息
CPU CPU使用情况
Cluster 集群信息
KeySpace 键值对统计数据信息

 

 

 

 

 

 

再谈分布式锁

当主节点挂掉了,从节点取而代之;但是有可能客户端申请成功了一把锁,但是此时主节点挂了,但是从节点也没有同步这个加锁的操作就升级成了主节点,那么这个时候就出问题了。另外一个客户端申请了锁,问题更大了,鸠占鹊巢

Redlock算法

需要导入redlock模块

加锁时:客户端向过半节点发送加锁请求,请求成功了就加锁成功;释放锁的时候,需要向所有节点发送del指令。

Redlock使用场景

但是很慢哦

过期策略

Redis所有的数据结构都可以设置过期时间,时间一到,就会被自动删除。

Redis是单线程的,收割的时间也会占用线程的处理时间,如果收割的太过频繁,会导致卡顿

过期的key的集合

Redis会将每个设置了过期时间的key放入一个独立的字典中,之后会定时遍历这个字典来删除到期的key。

除了定时删除,它还会使用惰性策略来删除过期的key。所谓惰性删除就是在客户端访问这个key的时候,Redis对key的过期时间进行检查,如果过期了就立即删除。

定时删除:集中处理

惰性删除:零散处理

定时扫描策略

默认每秒10次扫描

  1. 从过期字典中随机选出20个key
  2. 删除这20个key中已经过期的key
  3. 过期的key超过了1/4,那就重复一次

为了保证扫描不会出现循环过度,导致线程卡死的现象,算法还增加了扫描时间的上限,默认不会超过25ms

当客户端请求到来时,服务器如果正好进入过期扫描状态,客户端的请求将会等待至少25ms才会处理,如果客户端将超时时间设置得比较短,那么就会出现很多超时关闭。

所以业务开发人员一定要注意过期时间,如果有大批量得key过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期。

通过随机化过期时间总是很好得解决定期扫描过期得事情。

从节点的过期策略

从节点不会过期扫描,从节点对过期得处理是被动得。主节点在key到期时,会在AOF文件中增加一条del指令。然后从节点删除过期得节点。但是可能导致主节点中删除了,但是从节点中没有删除得现象。

优胜劣汰-LRU

当Redis内存超出了物理内存限制时,内存得数据会开始和磁盘产生频繁得交换(Swap)。但是redis是不能存在数据交换操作得

所以当超内存之后会有以下机中方法:

  1. noeviction:不会继续服务写请求
  2. volatile-lru:尝试淘汰设置了过期时间得key,最少使用得key优先被淘汰
  3. volatile-ttl:比较设置过过期时间得key,但是比较每个key剩余得生命ttl,来选择淘汰得key
  4. volatile-random:跟上面得一样,但是淘汰得是过期得key集合
  5. allkeys-lru:对所有得key来一次lru
  6. allkeys-random:淘汰得随机得key

总结:volatile-xxx只针对带过期时间得key进行淘汰,allkeys-xxx策略会对所有得key进行淘汰。

LRU算法

实现LRU算法除了需要key/value字典外,还需要附加一个链表。

当空间满的时候,会踢掉链表尾部的元素。当字典的某个元素被访问,就会被移动到表头。所以链表的元素排列就是元素最近被访问的时间顺序。

近似LRU算法

Redis使用的是一种近似的LRU算法,跟Lru算法有一点不一样。之所以不适用Lru算法,是因为需要大量的额外空间。

Redis给每个key增加一个额外的小字段,这个字段的长度是24个bit,也就是最后一个被访问的时间戳。

RedisLru算法采用的是懒惰处理,随机采样5个key,然后淘汰最旧的key,如果淘汰后还是超内存,就继续采样淘汰。

是否只对设置了过期的key进行LRU算法,取决于maxmemory-policy设置。

删除的东西会放在淘汰池中,慢慢删除。

懒惰删除

后台删除线程

Redis为什么使用懒惰删除

删除大对象还是很慢的,所以要异步丢给后台删除线程处理

flush

flushdb、flushall都是很慢的操作,因为是直接删除完,但是可以flushall async丢给后台线程慢慢处理

异步队列

一头再往里面加删除的数据,一边在删除,所以这个队列需要线程安全的

AOF Sync

也是开辟一个线程,进行实时的同步写日志文件

更多异步删除点

redis4.0给下面的指令也是带来的异步删除

slave-lazy-flush:从节点接受完rdb文件后的flush操作

lazyfree-lazy-eviction:内存达到maxmemory时进行删除

lazyfree-lazy-expire key:过期删除

lazyfree-lazy-server-del rename:指令删除destKey

Jedis

Redis开源客户端

Jedispool,jedis连接池

需要使用try-with-resource语句来保护jedis对象,一定要释放连接啊。

重试

没有重试机制,需要自己写重试。

保护Redis

指令安全

  1. redis可以设置rename-command指令,给一些危险的指令重命名。

端口安全

不要使redis服务器的网址暴露在外面

Lua脚本安全

让redis以普通用户的方式启动,防止黑客拿到root权限

SSL代理

redis不支持SSL,意味着客户端和服务器之间的交互数据不能直接暴露在公网上传输。但是可以使用SSL代理。

使用spipedSSH对通道进行二次加密

Redis安全通信

使用ssl给数据加密

spiped原理

在客户端和服务器端都开启一个spiped的线程

一个加密和解密的过程

spiped进程监听一个端口接收数据,并且使用这个端口发送数据;客户端先将数据发送到piped上进行加密,然后传输到服务器端,服务器端进行解密,发送到服务器上。

spiped

可以同时支持多个客户端连接的数据转发工作,还可以通过参数来限定允许的最大客户端连接数,但是对于服务器spiped,它不能同时支持多个服务器之间的转发。需要为每一个server节点启动一个spiped进程来代收消息。

原文地址:https://www.cnblogs.com/sicheng-li/p/13299376.html