zoukankan      html  css  js  c++  java
  • redis知识汇总

      redis是一个内存数据库,使用key-value形式在内存中管理数据。

    一、redis使用场景

      1、热数据存储。对于需要频繁读写的数据,可以放到redis中,不用频繁的请求数据库。再设置策略持久化到数据库中。

      2、token管理。用户登录成功后,生成token,存储到redis中,并设置过期时间,可以模拟session,用于做认证中心。

      3、缓解数据库压力。大量并发请求访问数据库会造成数据库崩溃,可以使用redis做缓冲,先访问redis。 

    二、redis为啥这么块

      主要有3个原因:

    • 纯内存操作。所有的操作都是在内存中进行。
    • 单线程操作。单线程操作避免了频繁的上下文切换。
    • 使用非阻塞I/O多路复用机制。客户端会产生具有不同事件类型的socket。在服务端,有一段I/0多路复用程序,将socket置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。

    三、redis数据结构

    • string 就是常规的set/get操作
    • list 队列
    • set 不重复的集合
    • sorted set 有序的不重复集合
    • hash 结构化的对象。

    四、redis持久化

      在因为故障等原因导致服务停止时,内存的数据就会丢失。因此,需要将内存的数据持久化到硬盘上。

      redis持久化有两种方式:RDB、AOF

      1、RDB方式持久化

      是通过快照来完成的。当满足一定条件时,redis会将内存中的数据进行快照并存储到硬盘上。

      进行快照的条件在配置文件中配置,由两个参数构成:时间、改动键的个数。当在指定时间内,被改动键的个数大于指定个数时,则触发RDB持久化。

      配置文件中默认有3个条件,这些条件是或的关系。  

    1 save 900 1 # 15分钟内至少有一个键被更改 
    2 save 300 10 # 5分钟内至少有10个键被更改
    3 save 60 10000 # 1分钟内至少有10000个键被更改

      默认的rdb文件在当前的目录,文件名是dump.rdb。

      可以对Redis执行手动快照操作,命令是:save、bgsave。两者有区别:save是由主进程进行快照,会阻塞其他请求。bgsave通过fork子进程进行快照。

      注意:由于Redis使用fork来复制一份当前进程,那么子进程就会占有和主进程一样的内存资源,比如说主进程8G内存,那么在备份的时候,必须保证有16G的内存,要不然会启用虚拟内存,性能非常的差。

      2、AOF方式持久化

      是将发送到Redis服务端的每一条命令都记录下来,并且保存在硬盘的AOF文件中。

      可以通过参数appendonly来设置是否启用AOF。AOF文件的位置和RDB的位置相同,都是通过dir参数设置,默认的文件名是appendonly.aof,可以通过appendfilename参数修改。

    五、redis过期删除策略以及内存淘汰机制

      过期删除策略有:定时删除、惰性删除。

      定时删除:有一个定时器在定时随机扫描一些key,key过期了则删除。这种策略因为定时器一直在扫描,很消耗系统资源。同时有一些key到了过期时间也没有删除。

      惰性删除:在使用key的时候,再检查是否过期,过期了就删除。

      定时删除和惰性删除可以配合使用。

      有个问题是:如果有些key没有被定时删除任务扫描到,同时又长时间没有被调用到,那么这些key是不会被删除的。长期这样会占用大量内存。

      这就需要使用到内存淘汰机制。

      内存淘汰机制在配置文件中开启和配置:

      在redis.conf中有一行配置

    # maxmemory-policy volatile-lru

      有6种内存淘汰机制,一般使用的是:allkeys-lru。当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。

    六、问题

      1、redis和数据库一致性问题

        数据库和缓存双写,必然存在数据不一致问题,对数据有强一致性要求的不能将数据放到缓存中。

      2、缓存穿透。

        大量的请求没有请求缓存,而是都请求数据库了。一般发生在黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。 

      解决方案:

      (一)利用互斥锁。当请求从缓存中得不到数据时,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试,这样能避免大量的请求数据库。

      (二)采用异步更新策略。无论请求是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。

      (三)提供一个能迅速判断请求是否有效的拦截机制。比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出请求所携带的Key是否合法有效。如果不合法,则直接返回。

      3、缓存雪崩

        缓存在同一时间大面积失效,这时候又有大量的请求,则这些请求会请求到数据库,导致数据库异常。

      解决方案:

      (一)给缓存的失效时间加上一个随机值,避免集体失效。

      (二)使用互斥锁,避免大量数据库请求。

      (三)双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点:

    • 从缓存A读数据库,有则直接返回。
    • A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
    • 更新线程同时更新缓存A和缓存B。

      4、redis并发竞争key

        多个子系统去set一个value。

      解决方案:

      1、设置分布式锁,抢到锁的就去set。

      2、设置队列,根据实际需求将set操作变成串行。

  • 相关阅读:
    C语言 sprintf 函数 C语言零基础入门教程
    C语言 printf 函数 C语言零基础入门教程
    C语言 文件读写 fgets 函数 C语言零基础入门教程
    C语言 文件读写 fputs 函数 C语言零基础入门教程
    C语言 fprintf 函数 C语言零基础入门教程
    C语言 文件读写 fgetc 函数 C语言零基础入门教程
    C语言 文件读写 fputc 函数 C语言零基础入门教程
    C语言 strlen 函数 C语言零基础入门教程
    Brad Abrams关于Naming Conventions的演讲中涉及到的生词集解
    适配器模式
  • 原文地址:https://www.cnblogs.com/leanfish/p/9141385.html
Copyright © 2011-2022 走看看