以下是面试以来被问到过的题,当然也包括一些没被问的题,有备无患。
被问到过的
Redis跳表
链表加上多级索引的结构,称为跳表,应用在Redis ZSet数据结构当中。ZSet要求数据唯一有序,且支持插入删除。
实现
跳表包含zskiplistNode和skiplist两个结构定义。
- zskiplistNode表示跳表节点。
- zskiplist保存跳表节点的信息。
- 节点的数量,
- 表头节点和表尾节点的指针等等。
参考文章
缓存和数据库一致性
常见的四种更新策略
-
先更新数据库再更新缓存
- 线程安全角度:
2线程同时更新统一条数据,然后再更新缓存的时候无法保障缓存被更新的时间和数据库更新的时间一致。
- 线程安全角度:
-
先更新数据库再删缓存
对比操作1上增加了删除操作,可能会删除非脏值,但是不影响一致性。
- 步骤
- 查询:缓存空,查数据库放入缓存。/非空 直接查询缓存拿到数据。
- 更新:更新数据库,删除缓存。
- 极端情况:A读B写 针对统一条数据 此时缓存失效。
- A缓存读不到 去数据库拿到旧值。
- B写数据库。
- B删除缓存。
- A将数据库的旧值写入缓存。
- 极端情况解决:
- 要求B写操作比A读操作更快,不现实。
- 可在每一次写操作后再加上一次异步删除 双删保平安。
- 步骤
-
先删除缓存再更新数据库
- 若A写数据B读数据,
A删除缓存时候B读数据 此时B会读数据库更新缓存。出现脏数据。
- 解决办法:
加上休眠时间。A写完数据库后1S再次删除缓存
,但是在休眠时间内依然会出现脏数据。为避免吞吐量降低可以使用异步删除,队列或者异步线程均可。
- 若A写数据B读数据,
-
先更新缓存再更新数据库
- AB更新同一条数据 无法保证更新数据库的顺序和更新缓存的顺序一致,且更新缓存成功更新数据库失败无法容错。