• 如何保证Redis和数据库双写一致性的问题?


    Redis在国内各大公司都很热门,比如新浪、阿里、腾讯、百度、美团、小米等。Redis也是大厂面试最爱问的,尤其是Redis客户端、Redis高级功能、Redis持久化和开发运维常用问题探讨、Redis复制的原理和优化策略、Redis分布式解决方案等。

    关于Redis的这8问,你能答上来几个?

    1、为什么使用Redis

    项目中使用Redis,主要考虑性能和并发。如果仅仅是分布式锁这些,完全可以用中间件ZooKeeper等代替。

    性能:

    如下图所示,在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用Redis做一个缓冲操作,让请求先访问到Redis,而不是直接访问数据库。

    根据交互效果的不同,响应时间没有固定标准。在理想状态下,我们的页面跳转需要在瞬间解决,对于页内操作则需要在刹那间解决。

    并发:

    如下图所示,在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用Redis做一个缓冲操作,让请求先访问到Redis,而不是直接访问数据库。

    2、使用Redis有什么缺点?

    缓存和数据库双写一致性问题
    缓存雪崩问题
    缓存击穿问题
    缓存的并发竞争问题
    

    3、单线程的Redis为什么这么快?

    你知道Redis是单线程工作模型吗?

    纯内存操作
    单线程操作,避免了频繁的上下文切换
    采用了非阻塞I/O多路复用机制
    

    4、Redis的数据类型及使用场景

    (这5种类型你用到过几个?)

    String:一般做一些复杂的计数功能的缓存;

    Hash:单点登录;

    List:做简单的消息队列的功能;

    Set:做全局去重的功能;

    SortedSet:做排行榜应用,取TOPN操作;延时任务;做范围查找。

    5、Redis过期策略和内存淘汰机制?

    正解:Redis采用的是定期删除+惰性删除策略。

    为什么不用定时删除策略?
    定期删除+惰性删除是如何工作的呢?
    采用定期删除+惰性删除就没其他问题了么?
    

    6、Redis和数据库双写一致性问题

    (最终一致性和强一致性)

    如果对数据有强一致性要求,不能放缓存。

    7、如何应对缓存穿透和缓存雪崩问题

    缓存穿透:即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

    缓存雪崩:即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。

    中小型的公司一般遇不到这些问题,但是大并发的项目,流量有几百万左右,这两个问题一定要深刻考虑。

    8、如何解决Redis并发竞争Key问题?

    这个问题大致就是,同时有多个子系统去set一个key。不太推荐使用redis的事务机制。

    (1)如果对这个key操作,不要求顺序

    这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可。

    (2)如果对这个key操作,要求顺序

    假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC.

    期望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。假设时间戳如下

    系统A key 1 {valueA 3:00}
    系统B key 1 {valueB 3:05}
    系统C key 1 {valueC 3:10}

    那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。

    其他方法,比如利用队列,将set方法变成串行访问也可以。总之,灵活变通。

    烟哥彩蛋

    在面试中如果碰到下列问题,如何应用上本篇的知识呢?先明确一点,我推荐的是Redis Cluster。
    OK,开始举例说明

    问题1:懂Redis事务么?
    正常版:Redis事务是一些列redis命令的集合,blabla…
    高调版: 我们在生产上采用的是Redis Cluster集群架构,不同的key是有可能分配在不同的Redis节点上的,在这种情况下Redis的事务机制是不生效的。其次,Redis事务不支持回滚操作,简直是鸡肋!所以基本不用!

    问题2:Redis的多数据库机制,了解多少?
    正常版:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,单机下的redis可以支持16个数据库(db0 ~ db15)
    高调版: 在Redis Cluster集群架构下只有一个数据库空间,即db0。因此,我们没有使用Redis的多数据库功能!

    问题3:Redis集群机制中,你觉得有什么不足的地方吗?
    正常版: 不知道
    高调版: 假设我有一个key,对应的value是Hash类型的。如果Hash对象非常大,是不支持映射到不同节点的!只能映射到集群中的一个节点上!还有就是做批量操作比较麻烦!

    问题4:懂Redis的批量操作么?
    正常版: 懂一点。比如mset、mget操作等,blabla
    高调版: 我们在生产上采用的是Redis Cluster集群架构,不同的key会划分到不同的slot中,因此直接使用mset或者mget等操作是行不通的。

    问题5:那在Redis集群模式下,如何进行批量操作?
    正常版:不知道
    高调版:这个问题其实可以写一篇文章了,改天写。这里说一种有一个很简单的答法,足够面试用。即:
    如果执行的key数量比较少,就不用mget了,就用串行get操作。如果真的需要执行的key很多,就使用Hashtag保证这些key映射到同一台Redis节点上。简单来说语法如下

    对于key为{foo}.student1、{foo}.student2,{foo}student3,这类key一定是在同一个redis节点上。因为key中“{}”之间的字符串就是当前key的hash tags, 只有key中{ }中的部分才被用来做hash,因此计算出来的redis节点一定是同一个!
    

    ps:如果你用的是Proxy分片集群架构,例如Codis这种,会将mget/mset的多个key拆分成多个命令发往不同得Redis实例,这里不多说。我推荐答的还是Redis Cluster。

    问题6:你们有对Redis做读写分离么?
    正常版:没有做,至于原因额。。。额。。。额。。没办法了,硬着头皮扯~
    高调版:不做读写分离。我们用的是Redis Cluster的架构,是属于分片集群的架构。而Redis本身在内存上操作,不会涉及IO吞吐,即使读写分离也不会提升太多性能,Redis在生产上的主要问题是考虑容量,单机最多10-20G,key太多降低Redis性能.因此采用分片集群结构,已经能保证了我们的性能。其次,用上了读写分离后,还要考虑主从一致性,主从延迟等问题,徒增业务复杂度。

  • 相关阅读:
    android WebView总结
    Java抓取网页数据(原网页+Javascript返回数据)
    Linux之旅(1): diff, patch和quilt (下)
    浅谈UML的概念和模型之UML九种图
    基于注解的Spring MVC
    Hibernate自增列保存失败的问题
    京东,你玩我?
    MySQL 通配符学习小结
    Java中怎样由枚举常量的ordinal值获得枚举常量对象
    HDU 4588 Count The Carries 计算二进制进位总数
  • 原文地址:https://www.cnblogs.com/djwhome/p/12543540.html
Copyright © 2020-2023  润新知