zoukankan      html  css  js  c++  java
  • redis 的高并发的理解

    redis 的特点:

    • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    • Redis支持数据的备份,即master-slave模式的数据备份。

    redis 在并发下出现的情况:

    缓存穿透:

      用户发送数据(一条数据库中存在、redis中不存在的) 到redis中没有就去DB中查,如果DB中没有查询到,就返回给用户;若黑客使用这个漏洞 进行对数据库的攻击就会给数据库击垮。

    解决的办法:

      1、添加过期时间

      2、添加一个布隆过滤器   

      布隆过滤器( 加载120万的数据需要 9秒,)是数据哈希到一个足够大额 bigMap 中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力,但是布隆过滤器有个一误判率是大约是3%

      DB查询到数据为空的时候, 把数据写入到redis中 key对应的value就是空值, 并设置key 的过期时间,设置过期时间最好使用1-5的随机数,

      

    缓存击穿:

      用户发送请数据到redis中 发现redis的数据过期了。这个时候就会去查询数据库, 如果有大量的并发请求,发现有大量的数据在redis中过期了。这个时候就会给DB造成巨大的压力。

      解决的方法:

      1、设置redis中的key 为过期时间为随机数最大不超过5, 

      2、 在访问DB的时候加上锁, 如果是分布式就使用分布式锁。  使用互斥锁  (setNx )

    缓存雪崩:

      当redis中数据在某一个时间段存在大量的过期时间,就会去请求DB 这样会给数据库带来巨大的压力或者是击垮数据库。

    解决方法:

      在访问数据库的时候加锁

      设置队列关系

    缓存预热:

      就系统上线的时候需要把数据库中的数据缓存到redis中,这个样就可以避免用户在查询的数据时候在从数据库中查了。 

    解决的方法:

      1,系统上线后 实现都写好的执行缓存的刷新的页面进行操作。2,也可以手动的更新,3、定时刷新缓存 

    如果缓存的数据不多的话  设置项目启动就可以启动缓存更新。

    缓存更新:

      Redis默认的有6中策略可供选择

         比较常用有两种方案:

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

      2、 用户请求过来的时候,发现缓存中的数据过期了,在去数据库查在去根性·更新redis。

    缓存降级

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

    降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

    以参考日志级别设置预案:

    (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

    (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;

    (3)错误:比如可用率低

    redis  的命令 使用  :  

    与String相关的常用命令:

    • SET:为一个key设置value,可以配合EX/PX参数指定key的有效期,通过NX/XX参数针对key是否存在的情况进行区别操作,时间复杂度O(1)

    • GET:获取某个key对应的value,时间复杂度O(1)

    • GETSET:为一个key设置value,并返回该key的原value,时间复杂度O(1)

    • MSET:为多个key设置value,时间复杂度O(N)

    • MSETNX:同MSET,如果指定的key中有任意一个已存在,则不进行任何操作,时间复杂度O(N)

    • MGET:获取多个key对应的value,时间复杂度O(N)

    与List相关的常用命令:

    • LPUSH:向指定List的左侧(即头部)插入1个或多个元素,返回插入后的List长度。时间复杂度O(N),N为插入元素的数量

    • RPUSH:同LPUSH,向指定List的右侧(即尾部)插入1或多个元素

    • LPOP:从指定List的左侧(即头部)移除一个元素并返回,时间复杂度O(1)

    • RPOP:同LPOP,从指定List的右侧(即尾部)移除1个元素并返回

    • LPUSHX/RPUSHX:与LPUSH/RPUSH类似,区别在于,LPUSHX/RPUSHX操作的key如果不存在,则不会进行任何操作

    • LLEN:返回指定List的长度,时间复杂度O(1)

    • LRANGE:返回指定List中指定范围的元素(双端包含,即LRANGE key 0 10会返回11个元素),时间复杂度O(N)。应尽可能控制一次获取的元素数量,一次获取过大范围的List元素会导致延迟,同时对长度不可预知的List,避免使用LRANGE key 0 -1这样的完整遍历操作。


      应谨慎使用的List相关命令:

    • LINDEX:返回指定List指定index上的元素,如果index越界,返回nil。index数值是回环的,即-1代表List最后一个位置,-2代表List倒数第二个位置。时间复杂度O(N)

    • LSET:将指定List指定index上的元素设置为value,如果index越界则返回错误,时间复杂度O(N),如果操作的是头/尾部的元素,则时间复杂度为O(1)

    • LINSERT:向指定List中指定元素之前/之后插入一个新元素,并返回操作后的List长度。如果指定的元素不存在,返回-1。如果指定key不存在,不会进行任何操作,时间复杂度O(N)

    由于Redis的List是链表结构的,上述的三个命令的算法效率较低,需要对List进行遍历,命令的耗时无法预估,在List长度大的情况下耗时会明显增加,应谨慎使用。

    与Hash相关的常用命令:

    • HSET:将key对应的Hash中的field设置为value。如果该Hash不存在,会自动创建一个。时间复杂度O(1)

    • HGET:返回指定Hash中field字段的值,时间复杂度O(1)

    • HMSET/HMGET:同HSET和HGET,可以批量操作同一个key下的多个field,时间复杂度:O(N),N为一次操作的field数量

    • HSETNX:同HSET,但如field已经存在,HSETNX不会进行任何操作,时间复杂度O(1)

    • HEXISTS:判断指定Hash中field是否存在,存在返回1,不存在返回0,时间复杂度O(1)

    • HDEL:删除指定Hash中的field(1个或多个),时间复杂度:O(N),N为操作的field数量

    • HINCRBY:同INCRBY命令,对指定Hash中的一个field进行INCRBY,时间复杂度O(1)

    应谨慎使用的Hash相关命令:

    • HGETALL:返回指定Hash中所有的field-value对。返回结果为数组,数组中field和value交替出现。时间复杂度O(N)

    • HKEYS/HVALS:返回指定Hash中所有的field/value,时间复杂度O(N)

    上述三个命令都会对Hash进行完整遍历,Hash中的field数量与命令的耗时线性相关,对于尺寸不可预知的Hash,应严格避免使用上面三个命令,而改为使用HSCAN命令进行游标式的遍历,具体请见 

    https://redis.io/commands/scan

    --

    为什么redis是单线程模型也能效率也很高?

      1 纯内存操作

      2 核心是基于非阻塞的 io 多路复用机制

      3 单线程 反而避免了多线程上下文切换的问题。

    redis分布式锁:

    设置分布式锁 set my:lock 随机值 NX PX 30000
    (my 可以用 用户id或者是订单id等,随机值不能重复。NX:存在设置失败,反之就成功,px 设置过期时间)
    释放锁。 就是删除key 是根据随机值, 是根据redis中的随机值和key对应的随机值一致就删除。

  • 相关阅读:
    要求两个条件都为假时,执行某些操作
    Celery + RabbitMq 示意图
    关于消息队列的好文章
    django related_name, on_delete
    Celery 图,[转]
    django model 中 meta子类详解
    django 自定义app
    python __dict__
    Python SQLAlchemy基本操作和常用技巧(包含大量实例,非常好)【转】
    scala private
  • 原文地址:https://www.cnblogs.com/yishuo/p/12651439.html
Copyright © 2011-2022 走看看