• 李玥
    置顶
    2020-03-21
    Hi,我是李玥。 这里回顾一下上节课的思考题: 课后请你选一种你熟悉的非关系型数据库,最好是支持 SQL 的,当然,不支持 SQL 有自己的查询语言也可以。比如说 HBase、Redis 或者 MongoDB 等等都可以,尝试分析一下查询的执行过程,对比一下它的执行器和存储引擎与 MySQL 有什么不同。 谈一下我的理解: 我们拿一个分布式数据库Hive来看一下它的执行器和存储引擎。严格来说,Hive并不是一个数据库,它只是一个执行器,它的存储引擎就是HDFS加上Map-Reduce。在Hive中,一条SQL的执行过程是和MySQL差不多的,Hive会解析SQL,生成并优化逻辑执行计划,然后它就会把逻辑执行计划交给Map-Reduce去执行了,后续生成并优化物理执行计划,在HDFS上执行查询这些事儿,都是Map-Reduce去干的。顺便说一下,Hive的执行引擎(严格来说是物理执行引擎)是可以替换的,所以就有了Hive on Spark,Hive on Tez这些。
    
    34
  • Geek_3894f9
    2020-03-21
    数据加版本号,写库时自动增一。更新缓存时,只允许高版本数据覆盖低版本数据。

    作者回复: 👍👍👍

    共 19 条评论
    70
  • GaGi
    2020-03-21
    对于Cache aside和read/write through而带来的数据不一致问题,工作中是这样解决: a写线程,b读线程: b线程:读缓存->未命中->上写锁>从db读数据到缓存->释放锁; a线程:上写锁->写db->删除缓存/改缓存->释放锁; 这样来保证a,b线程并发读写缓存带来的脏数据问题;

    作者回复: 👍👍👍

    共 16 条评论
    41
  • 丁小明
    2020-03-27
    老师,经常看到说用布隆过滤来解决缓存穿透问题,这个方案有实际的案例吗? 如果是真的可以那么怎么去操作呢? 先初始化所有可能存到缓存里面数据的key到一个足够大的布隆过滤器,然后如果有新增数据就就继续往过滤器中放,删除就从过滤器里面删(又看到说不用bit的话支持累加删除) 如果发现不在过滤器中就表示一定不存在,就无需查询了。如果在过滤器中也有可能不存在,这个时候在配合null值。 这个方案靠谱么,希望老师能解答一下

    作者回复: 首先这是个经典的方案,靠谱是没问题的。它可以解决问题是,不用真正去查询数据集,就可以判断,请求的数据是不是,不在数据集内。如果不在就不用去查询数据集了。 不少数据库都内置了布隆过滤器来提升查询效率,比如HBase。 布隆过滤器的缺点就是有点复杂,实现难度还是挺大的。

    
    4
  • 任鹏斌
    2020-05-21
    老师Cache Aside应该是先删缓存后更新数据库吧?先更新数据库的话一旦缓存删除失败了,就会产生脏数据

    作者回复: 严格来说,在并发情况下,二种方式都有可能产生脏数据。Cache Aside Pattern建议,先操作数据库,再操作缓存。

    共 4 条评论
    3
  • 王杰
    2020-04-18
    作者回复: 你可以参考一下“GaGi”同学的留言,用锁来解决并发问题。------------------------------------------------------老师,在读线程上写锁(说独占锁比较合适),是否跟MVCC相违背,MVCC不就是为了用来解决高并发带来的读写阻塞问题吗?我这边有两种解决思路不知可否:第一用版本控制,类似MVCC,第二种用Read/Write Through,写写并发在MVCC模式下依然是阻塞的,不算违背,所以只要把更新数据库与更新缓存放入统一事务中就行。读写并发不阻塞,是因为mysql用了快照读原因,那我们可以继续写线程更新缓存,读线程采用redis的setnx方式解决覆盖

    作者回复: mvcc可以很好的解决读写冲突,但是对于写写冲突,要么加锁,要么引入冲突检测机制,否则就会导致写倾斜的问题。这个在23中有详细的说明。

    共 5 条评论
    3
  • image
    2020-03-26
    如果缓存时有大量命中为null如何处理?如果命中null 也进行缓存,会导致缓存增长太快,容易被攻击 如果不缓存,又容易引起大量穿透

    作者回复: 这种情况理论上也没有完美的解决方案,来说说实际上的一些处理经验。 首先,避免短时间大量人为的空值攻击,这个事儿应该在上层安全或者风控层面去解决。(即使无法判断是否空值攻击,至少要拦截住短时间大量的不正常访问请求) 剩余下来的就是业务上正常的查询返回空的情况,这种可能要从业务上来设计一下,尽量避免大量可能的空值查询。 以上2点做了之后,空值查询就会少多了,这个时候可以根据实际情况选择缓存空值,或者让空值穿透。

    
    3
  • 1
    2020-03-23
    是不是model的话使用缓存,列表的话是不是不适合用缓存?列表应该怎么去缓存?

    作者回复: 这个还是得看业务,很多列表也可以缓存的,比如说一些排行榜数据。

    
    
  • 蚂蚁内推+v
    2020-03-21
    Cache Aside解决的只是并发写请求导致的缓存数据不一致问题。对于读写这种场景并没有彻底解决。 A:读,缓存穿透,查库。 B:写,更新数据库。 B:写,删除缓存。 A:读,回写缓存。导致不一致。 目前针对这种问题我们这边才去的方案是写请求后用MQ延迟删除缓存。老师有什么好的方法和实践吗?

    作者回复: 你可以参考一下“GaGi”同学的留言,用锁来解决并发问题。

    共 2 条评论
    
  • 往事随风,顺其自然
    2020-03-21
    老师有个问题请教你,我这边有个业务,合同编号,存在redis 🀄️和数据库中,每次先查redis 获取合同编号后面虚寒,然好加1⃣️,保存回去,外去更新数据库,做了数据库合同编号重复,检验,但是每次还是有合通编号重复的,请问这个怎么解决?市并发导致?

    作者回复: 使用Redis命令INCR是可以保存原子性的。 如果是GET出来,在程序内加一,在SET回去,确实会存在并发问题。

    共 3 条评论
    