缓存机制以及Redis,Redis的数据结构,缓存使用模式和经常遇到的问题。

什么是缓存?为什么要使用缓存?

主要讨论内存缓存,常见的有Redis和Memcached

  • 缓解关系型数据库并发访问的压力: 热点数据。
  • 减少响应时间:内存IO速度比磁盘快。
  • 提升吞吐量: Redis等内存型数据库单机就可以支持很大的并发。

     Redis和Memcached的区别

  

 

 

 

Redis的常用数据类型和使用场景

  • 字符串(String):用来实现简单的KV键值对存储,比如计数器。
  • 链表(List):实现双向链表,比如用户的关注、粉丝列表。
  • 哈希(Hash):用来存储彼此相关信息的键值对。
  • 集合(Set):存储不重复元素,比如用户的关注者。
  • 有序集合(Sorted Set):实时信息排行榜。

 

Redis 数据结构内置实现

实现Redis数据类型的底层C数据类型。

  字符串:整数或者sds(Simple Dynamic String 这个是Redis自己实现的一种字符串数据结构)。

  链表:ziplist(压缩链表)或者double linked list。

  哈希:ziplist或者hashtable(哈希表)。

  集合: inset或者hashtable。

  有序集合:skiplist 跳跃表。

  跳跃表结构: 

 

 

更多细节可以看 《Redis设计与实现》

 

Redis持久化

  • 快照方式:把数据快照放在磁盘二进制文件中,dump.rdb 可以用来恢复数据库的状态。
  • AOF(Append Only File): 每一个写命令追加到appendonly.aof中(缺点:文件比较大)
  • 通过修改Redis配置来选择上述两个持久化方式。

 

Redis事务

和mysql事务有什么不同? mysql事务:可以看做多个SQL语句,要么全部执行成功,要么全部执行失败(回滚)

  • 将多个请求打包,一次性,按序执行多个命令的机制。
  • Redis 通过 MULIT(添加), EXEC(执行), WATCH等命令实现事物功能。
  • python中 Redis.py  pipline=conn.pipline(transaction=True)

 

Redis如何实现分布式锁

  Redis服务器设置一个k v值,访问redis的时候,查看kv是否存在,不存在就进行操作,存在就等待或者重试。

  • 使用setnx实现加锁,可以通过expire添加超时时间。
  • 锁的value值可以使用一个随机的uuid或者特定的命名。
  • 释放锁的时候,通过uuid判断是否是该锁,是则执行delete释放锁。

 

Redis缓存模式

  • Cache Aside: 同时更新缓存和数据库。
  • Read/Write Through: 先更新缓存,缓存负责同步更新数据库。
  • Write Behind Caching: 先更新缓存,缓存定期异步更新数据库。

Redis常见问题

  •  缓存穿透问题:大量查不到数据的请求落到后端数据库,数据库压力增大:比如很多无脑爬虫通过自增id的方式爬取网站,但是数据id不是自增的,Redis和mysql都没有相关的数据。
    • 解决:对于没查到的返回None,None这个数据也缓存到Redis里。 插入数据的时候,删除掉缓存或者这个缓存本身设置较短时间。
  •    缓存击穿问题:某些非常热点的数据Key过期,大量请求打到后端数据库(比如微博热点之类的)。
    • 解决: 分布式锁,获取到锁的线程从数据库拉取数据然后更新缓存,其他线程等待。
    • 解决: 异步后台更新异步任务定期对快要过期的key自动更新,然后刷新过期时间。
  •   缓存的雪崩问题:大量缓存不可用或者大量Key同时失效, Redis数据库挂掉 -> 大量缓存不可用。
    • 解决: 多级缓存, 不同级别的key设置不同的超时时间
    • 解决: key的超时时间随机设置,防止同时超时。
    • 结构层:提升系统的可用性。监控、报警完善。

 

posted @ 2022-03-02 11:36  DRQ丶  阅读(109)  评论(0编辑  收藏  举报