zoukankan      html  css  js  c++  java
  • Redis常见的疑问总结

    -------------------------------------Redis常问到的问题:
    1、Redis的内存回收详解
      1.1 为何要回收内存
       Answer:reids作为内存性数据库,只进不出,内存迟早撑爆
      1.2 内存从哪里回收
       Answer:存储键值对消耗和本身运行消耗(过期键值和内存淘汰机制)
      1.3 如何实现对过期键值对的删除
       Answer:1)过期键值:内存充足时采用的算法,惰性删除和定期删除结合(惰性删除是被动的删除方式,在获取键值时,判断过期了,就删除,然而定期删除,是每隔特定的时间对redisDB进行扫描,判断过期了,就删除)
              2)内存淘汰机制:内存不充足时采用的算法,基于LRU策略进行淘汰即最近最少用的键淘汰使用
    2、Redis的持久化机制
       2.1 为何要持久化
        Answer:reids作为内存性数据库,一旦发生宕机,想必会造成数据的丢失(两大利器:RDB将数据库快照以二进制的方式保存到磁盘中
                                                        和AOF以协议文本方式,将所有对数据库进行过写入的命令和参数记录到 AOF 文件,从而记录数据库状态)
    3、Redis的应用场景
       底层实现:主要是从Redis的源码中提炼的问题,包括但不限于底层数据结构、服务模型、算法设计等。
       基础架构:可用概况为Redis整体对外的功能点和表现,包括但不限于单机版主从架构实现、主从数据同步、哨兵机制、集群实现、分布式一致性、故障迁移等。
       实际应用:实战中Redis可用帮你做什么,包括但不限于单机缓存、分布式缓存、分布式锁、一些应用。
     
     
    -----------------------------------Redis数据结构
    一、String(字符串)
    SET key value                   设置key=value
    GET key                         或者键key对应的值
    GETRANGE key start end          得到字符串的子字符串存放在一个键
    GETSET key value                设置键的字符串值,并返回旧值
    GETBIT key offset               返回存储在键位值的字符串值的偏移
    MGET key1 [key2..]              得到所有的给定键的值
    SETBIT key offset value         设置或清除该位在存储在键的字符串值偏移
    SETEX key seconds value         键到期时设置值
    SETNX key value                 设置键的值,只有当该键不存在
    SETRANGE key offset value       覆盖字符串的一部分从指定键的偏移
    STRLEN key                      得到存储在键的值的长度
    MSET key value [key value...]   设置多个键和多个值
    MSETNX key value [key value...] 设置多个键多个值,只有在当没有按键的存在时
    PSETEX key milliseconds value   设置键的毫秒值和到期时间
    INCR key                        增加键的整数值一次
    INCRBY key increment            由给定的数量递增键的整数值
    INCRBYFLOAT key increment       由给定的数量递增键的浮点值
    DECR key                        递减键一次的整数值
    DECRBY key decrement            由给定数目递减键的整数值
    APPEND key value                追加值到一个键
    二、Hash(哈希)
    HDEL key field[field...]         删除对象的一个或几个属性域,不存在的属性将被忽略
     
    HEXISTS key field             查看对象是否存在该属性域
     
    HGET key field                 获取对象中该field属性域的值
     
    HGETALL key                 获取对象的所有属性域和值
     
    HINCRBY key field value         将该对象中指定域的值增加给定的value,原子自增操作,只能是integer的属性值可以使用
     
    HINCRBYFLOAT key field increment     将该对象中指定域的值增加给定的浮点数
     
    HKEYS key                 获取对象的所有属性字段
     
    HVALS key                 获取对象的所有属性值
     
    HLEN key                 获取对象的所有属性字段的总数
     
    HMGET key field[field...]         获取对象的一个或多个指定字段的值
     
    HSET key field value             设置对象指定字段的值
     
    HMSET key field value [field value ...] 同时设置对象中一个或多个字段的值
     
    HSETNX key field value             只在对象不存在指定的字段时才设置字段的值
     
    HSTRLEN key field             返回对象指定field的value的字符串长度,如果该对象或者field不存在,返回0.
     
    HSCAN key cursor [MATCH pattern] [COUNT count]     类似SCAN命令
    三、List(列表)
    BLPOP key1 [key2 ] timeout 取出并获取列表中的第一个元素,或阻塞,直到有可用
     
    BRPOP key1 [key2 ] timeout 取出并获取列表中的最后一个元素,或阻塞,直到有可用
     
    BRPOPLPUSH source destination timeout 从列表中弹出一个值,它推到另一个列表并返回它;或阻塞,直到有可用
     
    LINDEX key index                     从一个列表其索引获取对应的元素
     
    LINSERT key BEFORE|AFTER pivot value 在列表中的其他元素之后或之前插入一个元素
     
    LLEN key                             获取列表的长度
     
    LPOP key                             获取并取出列表中的第一个元素
     
    LPUSH key value1 [value2]            在前面加上一个或多个值的列表
     
    LPUSHX key value                     在前面加上一个值列表,仅当列表中存在
     
    LRANGE key start stop                从一个列表获取各种元素
     
    LREM key count value                 从列表中删除元素
     
    LSET key index value                 在列表中的索引设置一个元素的值
     
    LTRIM key start stop                 修剪列表到指定的范围内
     
    RPOP key                             取出并获取列表中的最后一个元素
     
    RPOPLPUSH source destination         删除最后一个元素的列表,将其附加到另一个列表并返回它
     
    RPUSH key value1 [value2]            添加一个或多个值到列表
     
    RPUSHX key value                     添加一个值列表,仅当列表中存在
     
    四、Set(集合)
    SADD key member [member ...]                 添加一个或者多个元素到集合(set)里
     
    SCARD key                                    获取集合里面的元素数量
     
    SDIFF key [key ...]                          获得队列不存在的元素
     
    SDIFFSTORE destination key [key ...]         获得队列不存在的元素,并存储在一个关键的结果集
     
    SINTER key [key ...]                         获得两个集合的交集
     
    SINTERSTORE destination key [key ...]        获得两个集合的交集,并存储在一个集合中
     
    SISMEMBER key member                         确定一个给定的值是一个集合的成员
     
    SMEMBERS key                                 获取集合里面的所有key
     
    SMOVE source destination member              移动集合里面的一个key到另一个集合
     
    SPOP key [count]                             获取并删除一个集合里面的元素
     
    SRANDMEMBER key [count]                      从集合里面随机获取一个元素
     
    SREM key member [member ...]                 从集合里删除一个或多个元素,不存在的元素会被忽略
     
    SUNION key [key ...]                         添加多个set元素
     
    SUNIONSTORE destination key [key ...]        合并set元素,并将结果存入新的set里面
     
    SSCAN key cursor [MATCH pattern] [COUNT count]迭代set里面的元素
    五、ZSet(有序集合)
    ZADD key score1 member1 [score2 member2]     添加一个或多个成员到有序集合,或者如果它已经存在更新其分数
     
    ZCARD key                                    得到的有序集合成员的数量
     
    ZCOUNT key min max                           计算一个有序集合成员与给定值范围内的分数
     
    ZINCRBY key increment member                 在有序集合增加成员的分数
     
    ZINTERSTORE destination numkeys key [key ...]多重交叉排序集合,并存储生成一个新的键有序集合。
     
    ZLEXCOUNT key min max                        计算一个给定的字典范围之间的有序集合成员的数量
     
    ZRANGE key start stop [WITHSCORES]           由索引返回一个成员范围的有序集合(从低到高)
     
    ZRANGEBYLEX key min max [LIMIT offset count] 返回一个成员范围的有序集合(由字典范围)
     
    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]返回有序集key中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员,有序集成员按 score 值递增(从小到大)次序排列
     
    ZRANK key member                              确定成员的索引中有序集合
     
    ZREM key member [member ...]                  从有序集合中删除一个或多个成员,不存在的成员将被忽略
     
    ZREMRANGEBYLEX key min max                    删除所有成员在给定的字典范围之间的有序集合
     
    ZREMRANGEBYRANK key start stop                在给定的索引之内删除所有成员的有序集合
     
    ZREMRANGEBYSCORE key min max                  在给定的分数之内删除所有成员的有序集合
     
    ZREVRANGE key start stop [WITHSCORES]         返回一个成员范围的有序集合,通过索引,以分数排序,从高分到低分
     
    ZREVRANGEBYSCORE key max min [WITHSCORES]     返回一个成员范围的有序集合,以socre排序从高到低
     
    ZREVRANK key member                           确定一个有序集合成员的索引,以分数排序,从高分到低分
     
    ZSCORE key member                             获取给定成员相关联的分数在一个有序集合
     
    ZUNIONSTORE destination numkeys key [key ...] 添加多个集排序,所得排序集合存储在一个新的键
     
    ZSCAN key cursor [MATCH pattern] [COUNT count]增量迭代排序元素集和相关的分数
     
    ---------------Redis事务
    Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
    1、批量操作在发送 EXEC 命令前被放入队列缓存。
    2、收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
    3、在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
     
    一个事务从开始到执行会经历以下三个阶段:
     
    1.开始事务。
     
    2.命令入队。
     
    3.执行事务。
     
    -----------------Redis安全
    通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证。默认情况下 requirepass 参数是空的,
    这就意味着你无需通过密码验证就可以连接到 redis 服务。可以通过以下命令来修改该参数:
     
    127.0.0.1:6379> CONFIG set requirepass "test"
     
    ------------------Redis失效带来的问题
     
    1、redis穿透
    1.1什么是缓存穿透?
    业务系统要查询的数据根本就不存在!当业务系统发起查询时,按照上述流程,首先会前往缓存中查询,由于缓存中不存在,然后再前往数据库中查询。
     
    由于该数据压根就不存在,因此数据库也返回空。这就是缓存穿透。
     
    1.2 缓存穿透的危害
    如果存在海量请求查询压根就不存在的数据,那么这些海量请求都会落到数据库中,数据库压力剧增,可能会导致系统崩溃(你要知道,目前业务系统中最脆弱的就是IO,
     
    稍微来点压力它就会崩溃,所以我们要想种种办法保护它)。
    1.3 为什么会发生缓存穿透?
    发生缓存穿透的原因有很多,一般为如下两种:
     
    恶意攻击,故意营造大量不存在的数据请求我们的服务,由于缓存中并不存在这些数据,因此海量请求均落在数据库中,从而可能会导致数据库崩溃。
     
    代码逻辑错误。这是程序员的锅,没啥好讲的,开发中一定要避免!
     
    1.4 缓存穿透的解决方案
    下面来介绍两种防止缓存穿透的手段。
     
    1.4.1 【缓存空数据】
    之所以发生缓存穿透,是因为缓存中没有存储这些空数据的key,导致这些请求全都打到数据库上。
     
    那么,我们可以稍微修改一下业务系统的代码,将数据库查询结果为空的key也存储在缓存中。当后续又出现该key的查询请求时,缓存直接返回null,而无需查询数据库。
     
    1.4.2 【BloomFilter】
    第二种避免缓存穿透的方式即为使用BloomFilter。
    它需要在缓存之前再加一道屏障,里面存储目前数据库中存在的所有key,如下图所示:
    当业务系统有查询请求的时候,首先去BloomFilter中查询该key是否存在。若不存在,则说明数据库中也不存在该数据,因此缓存都不要查了,直接返回null。
    若存在,则继续执行后续的流程,先前往缓存中查询,缓存中没有的话再前往数据库中的查询。
     
    2.1 什么是缓存雪崩?
    通过上文可知,缓存其实扮演了一个保护数据库的角色。它帮数据库抵挡大量的查询请求,从而避免脆弱的数据库受到伤害。
     
    如果缓存因某种原因发生了宕机,那么原本被缓存抵挡的海量查询请求就会像疯狗一样涌向数据库。此时数据库如果抵挡不了这巨大的压力,它就会崩溃。
     
    这就是缓存雪崩。
     
    2.2 如何避免缓存雪崩?
     
    2.2.1 【使用缓存集群,保证缓存高可用】
    也就是在雪崩发生之前,做好预防手段,防止雪崩的发生。
    PS:关于分布式高可用问题不是今天讨论的重点,套路就那些,后面会有高可用的相关文章,尽请关注。
     
    2.2.2 【使用Hystrix】
    Hystrix是一款开源的“防雪崩工具”,它通过 熔断、降级、限流三个手段来降低雪崩发生后的损失。
     
    Hystrix就是一个Java类库,它采用命令模式,每一项服务处理请求都有各自的处理器。所有的请求都要经过各自的处理器。处理器会记录当前服务的请求失败率。
    一旦发现当前服务的请求失败率达到预设的值,Hystrix将会拒绝随后该服务的所有请求,直接返回一个预设的结果。这就是所谓的“熔断”。当经过一段时间后,
    Hystrix会放行该服务的一部分请求,再次统计它的请求失败率。如果此时请求失败率符合预设值,则完全打开限流开关;如果请求失败率仍然很高,
    那么继续拒绝该服务的所有请求。这就是所谓的“限流”。而Hystrix向那些被拒绝的请求直接返回一个预设结果,被称为“降级”。
     
    3、缓存并发
    3.1 什么是缓存并发?
    Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以Redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,
     
    但是利用jedis等客户端对Redis进行并发访问时会出现问题。
     
    3.2 如何避免Redis并发竞争的解决方案?
    3.2.1 【Redis分布式锁的实现】
    主要用到的redis函数是setnx()
     
    用SETNX实现分布式锁
     
    利用SETNX非常简单地实现分布式锁。例如:某客户端要获得一个名字youzhi的锁,客户端使用下面的命令进行获取:
     
    SETNX lock.youzhi<current Unix time + lock timeout + 1>
     
    如返回1,则该客户端获得锁,把lock.youzhi的键值设置为时间值表示该键已被锁定,该客户端最后可以通过DEL lock.foo来释放该锁。
    如返回0,表明该锁已被其他客户端取得,这时我们可以先返回或进行重试等对方完成或等待锁超时。
     
    3.2.2 【利用消息队列】
     
    在并发量过大的情况下,可以通过消息中间件进行处理,把并行读写进行串行化。
     
    把Redis.set操作放在队列中使其串行化,必须的一个一个执行。
     
    这种方式在一些高并发的场景中算是一种通用的解决方案。
     
     
     
    知人者智,自知者明,胜人者有力,自胜者强。
  • 相关阅读:
    (bfs入门)宝岛探险
    (bfs入门)走迷宫
    环形的处理P1880 [NOI1995]石子合并
    ZOJ2227Minimax三角划分
    UVA11400 Lighting System Design
    字符串匹配入门
    UVA12563 Jin Ge Jin Qu hao
    HDU1619 Unidirectional TSP
    ZOJ2581Tour
    UVA1025 A Spy in the Metro
  • 原文地址:https://www.cnblogs.com/nanfengxiangbei/p/14189661.html
Copyright © 2011-2022 走看看