Redis

Redis

一、简介:

    redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value的NoSql数据库。

二、特点

优点:  速度快、高性能                           

             数据类型丰富                                  

             基于内存存储,又支持持久化

             支持事务

缺点:不具备自动容错和恢复功能

            较难支持在线扩容

三、数据类型:

    1、字符串

       字符串类型是redis最基础的数据结构,首先键是字符串类型,而且其他几种结构都是 在字符串类型基础上构建的,所以字符串类型能为其他四种数据结构的学习尊定基础。字符  串类型实际上可以是字符串(简单的字符串、复杂的字符串(xml、json)、数字(整数、浮   点数)、二进制(图片、音频、视频)),但最大不能超过512M。

    使用场景:

       [缓存功能]:字符串最经典的使用场景,redis最为缓存层,Mysql作为储存层,绝大 部分请求数据都是redis中获取,由于redis具有支撑高并发特性,所以缓存通常能起到加  速读写和降低 后端压力的作用。

       [计数器]:许多运用都会使用redis作为计数的基础工具,他可以实现快速计数、查询 缓存的功能,同时数据可以一步落地到其他的数据源。如:视频播放数系统就是使用redis   作为视频播放数计数的基础组件。

       [共享session]:出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服   务器上,用户刷新一次访问可能会需要重新登录,为避免这个问题可以用redis将用户  session集中管理,在这种模式下只要保证redis的高可用和扩展性的,每次获取用户更新    或查询登录信息都直接从redis中集中获取。

       [限速]:处于安全考虑,每次进行登录时让用户输入手机验证码,为了短信接口不被频 繁访问,会限制用户每分钟获取验证码的频率。

 

    2、哈希

       在redis中哈希类型是指键本身又是一种键值对结构,value={{k,v},......{k,v}} 

    使用场景:

      哈希结构相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷。所以常  常用于**用户信息**等管理,但是哈希类型和关系型数据库有所不同,哈希类型是稀疏的, 而关系型数据库是完全结构化的,关系型数据库可以做复杂的关系查询,而redis去模拟  关系型复杂查询开发困难,维护成本高。

 

    3、列表

       列表类型是用来储存多个有序的字符串,列表中的每个字符串成为元素(element),一 个列表最多可以储存2的32次方-1个元素,在redis中,可以队列表两端插入(pubsh)   和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下表的元素等,列表是一种   比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发中有很多应用场景。

    优点:

    1.列表的元素是有序的,这就意味着可以通过索引下标获取某个或某个范围内的元素列表。

    2.列表内的元素是可以重复的。

    使用场景:

       [消息队列]: redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端是用  lupsh从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞时的“抢”列表尾部的    元素,多个客户端保证了消费的负载均衡和高可用性

       [文章列表]:每个用户都有属于自己的文章列表,现在需要分页展示文章列表,此时可 以考虑使用列表,列表不但有序同时支持按照索引范围获取元素。

 

    使用列表技巧:

    lpush+lpop=Stack(栈)

    lpush+rpop=Queue(队列)

    lpush+ltrim=Capped Collection(有限集合)

    lpush+brpop=Message Queue(消息队列)

 

    4、集合

       集合类型也是用来保存多个字符串的元素,但和列表不同的是集合中不允许有重复的元 素,并且集合中的元素是无序的,不能通过索引下标获取元素,redis除了支持集合内的增 删改查,同时还支持多个集合取交集、并集、差集,并合理的使用好集合类型,能在实际开    发中解决很多实际问题。

    使用场景:

       [ 标签(tag)]:集合类型比较典型的使用场景,如一个用户对娱乐、体育比较感兴趣, 另一个可能对新闻感兴趣,这些兴趣就是标签,有了这些数据就可以得到同一标签的人,以   及用户的共同爱好的标签,这些数据对于用户体验以及曾强用户粘度比较重要。

    sadd=tagging(标签)

    spop/srandmember=random item(生成随机数,比如抽奖)

    sadd+sinter=social Graph(社交需求)

 

    5、有序集合

       有序集合和集合有着必然的联系,他保留了集合不能有重复成员的特性,但不同得是, 有序集合中的元素是可以排序的,但是它和列表的使用索引下标作为排序依据不同的是,它  给每个元素设置一个分数,作为排序的依据。(有序集合中的元素不可以重复,但是csore 可以重复,就和一个班里的同学学号不能重复,但考试成绩可以相同).

    使用场景

       [排行榜]:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜 单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。

 

四、数据结构

   1、字符串

      动态字符串,String采用预分配冗余空间的方法。

   2、哈希

      类似与java语言的hashmap,也是无序的二维结构,也即数组加列表的结构,然而也有 不同,比如rehash,刷新字典操作,hashmap是全部热hash,当字典足够多时,性能不是  很好的,所以redis进行改造,采用渐进式的方式,为什么说是渐进式?因为redis不会全    部reload,而是保存新旧两个字典,然后采用定时任务,将旧hash的数据搬到新的hash,    搬后在回收hash内存空间。

       https://i-blog.csdnimg.cn/blog_migrate/b048ae2149e374f9cea119d41a073dbc.png

   3、列表

      采用快速列表,由压缩列表双向的指针组成,如图,减少内存空间

        https://i-blog.csdnimg.cn/blog_migrate/d1c2c5381d71ab103467610761b2c610.png

   4、集合

         类似java里的set集合。

   5、有序集合

      有序集合是redis里比较有特色的,它类似于SortedSet和HashMap的组合。其内部实 现是一种被称作跳跃列表的数据结构。有序集合一方面它就是一个set,所以每个元素都是  唯一的,然后它可以给每个value赋值一个score,再根据这个score进行排序,score就 相当于一个权限排序的标识。

        

五、持久化

   RDB:

   AOF:

   AOF重写:

六、主从集群

 

 

七、为什么这么快?

    1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

    2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

    3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

    4、使用 多路复用非阻塞I/O 模型;

        多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

    5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

八、Redis事务

       redis中的事务跟关系型数据库中的事务是一个相似的概念,但是有不同之处。关系型数据库事务执行失败后面的sql语句不在执行,而redis中的一条命令执行失败,其余的命令照常执行。

       redis中开启一个事务(断开连接)是使用multi,相当于begin tran,exec提交事务,discard丢弃事务(恢复连接),watch / unwatch 监控key,当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。

      >Redis会将一个事务中的所有命令序列化,然后按顺序执行。Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证Redis将这些命令作为一个单独的隔离操作执行。

      > 在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行。因此,Redis事务能够保证原子性。EXEC命令会触发执行事务中的所有命令。因此,当某个客户端正在执行一次事务时,如果它在调用MULTI命令之前就从Redis服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用EXEC命令之后才从Redis服务端断开连接,那么就会执行事务中的所有操作。当Redis使用只增文件(AOF:Append-only File)时,Redis能够确保使用一个单独的write 系统调用,这样便能将事务写入磁盘。然而,如果Redis服务器宕机,或者系统管理员以某种方式停止Redis服务进程的运行,那么Redis很有可能只执行了事务中的一部分操作。Redis将会在重新启动时检查上述状态,然后退出运行,并且输出报错信息。使用redis-check-aof工具可以修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样Redis服务器才能再次启动。

      redis的高级事务CAS(乐观锁)

      check-and-set(乐观锁)

      乐观锁介绍:
              watch指令在redis事物中提供了CAS的行为。为了检测被watch的keys在是否有多个clients同时改变引起冲突,这些keys将会被监控。如果至少有一个被监控的key在执行exec命令前被修改,整个事物将会回滚,不执行任何动作,从而保证原子性操作,并且执行exec会得到null的回复。

      乐观锁工作机制:
              watch 命令会监视给定的每一个key,当exec时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec,discard,unwatch命令,及客户端连接关闭都会清除连接中的所有监视。还有,如果watch一个不稳定(有生命周期)的key并且此key自然过期,exec仍然会执行事务队列的指令。

九、其他

   缓存雪崩:

    由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

    解决办法: 将缓存失效时间分散开

 

   缓存穿透:

    缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

   解决办法:①最常见的则是采用布隆过滤器 ②查询的空数据也进行缓存

 

    缓存预热:

    缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

 

    缓存更新:

    除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:

    1、定时去清理过期的缓存;

    2、当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

 

    缓存降级:

    当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

   

    内存淘汰机制:

    redis 内存数据集大小上升到一定大小的时候,就会进行数据淘汰策略。

    内存淘汰策略:

    volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。

    volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。

    volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。

    allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。

    allkeys-random:从数据集中任意选择数据淘汰,当内存达到限制的时候,对所有数据集挑选随机淘汰,可写入新的数据集。

    no-enviction:当内存达到限制的时候,不淘汰任何数据,不可写入任何数据集,所有引起申请内存的命令会报错。

   

    为什么单线程?

      redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis 用 单个CPU 绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的,所以它是单线程处理这个事。在内存的情况下,这个方案就是最佳方案

 

使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值