抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

什么是Redis?

Redis是一个使用C语言编写的、开源的、高性能的、非关系的、键值对数据库。

Redis中可以存储 键 和五种数据类型的值,其中键只能是字符串、值可以是字符串、列表、哈希、集合、有序集合。

Redis与传统的数据库不同的点是它存储在内存中,所以读写速度非常快,可以达到每秒处理10万次读/写的操作,是一只性能最快的key-value数据库,因此它经常被来用作缓存。同时它也被做来当分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

Redis的优缺点

优点

  1. 读写性能优异,可以达到每秒10万次读写操作。
  2. 支持数据持久化,支持AOF和RDB两种方式。
  3. 支持事务。
  4. 操作原子性。
  5. 有丰富的数据类型
  6. 支持主从、集群。

缺点

  1. 受到内存容量的限制,不能用作大数据的读写操作。
  2. 比较难在线扩容。

为什么使用缓存

现在的WEB系统的读写比是1:9或者3:7,所以读的次数是大于写的次数。因此如果我们将数据放置在内存中,就能够让服务端直接去内存中读取数据,提高系统的响应速度(高性能),并且能够减轻数据库的负担(高并发)。

使用Redis做缓存时需要注意什么

由于内存的容量限制问题或者说是成本的问题,我们使用Redis存储数据时一般只存储主要的数据,在存储数据时我们要考虑几个方面。

  1. 该业务数据经常使用嘛?命中率如何?
  2. 该业务数据是读操作多吗?写操作多吗?
  3. 业务数据的大小如何?

使用缓存会带来什么问题?

缓存雪崩

缓存同一时间大量失效,因此请求访问都访问去数据库中,大量的请求到数据库上,会导致数据库被打死因而宕机。

我们可以通过设置随机数,使得缓存不在同一时间失效。

缓存穿透

用户大量查询不在缓存中的数据,因此请求都发送到数据库中,如果请求多了可能会将数据库打死因而宕机。

我们可以通过布隆过滤器来过滤拦截,或者将查询的对象也存储在缓存中并设置较短的时间。

缓存与数据库双写一致性的问题

对于更新操作来说、可以分为两部分:操作缓存和操作数据库。根据先后顺序又分为两种操作:

  1. 先操作缓存、再操作数据库。
  2. 先操作数据库、再操作缓存。

但无论是那种,这都是两步操作,他不能保证原子性,因此可能会出现一步操作成功、一步操作失败的情况。

如果第一步已经失败了,我们直接返回Exception出去就好了,第二步根本不会执行。

操作缓存

操作缓存可以分为两种:更新缓存、删除缓存。但在一般情况下我们都选择删除缓存,因为如果再频繁更新数据的情况下,我们选择更新缓存的话,就会降低效率同时命中率也会很低,另外我们只在需要的时候再加载进缓存也可以减少内存占用(懒加载的思想)。

先更新数据库、再删除缓存

最理想的情况下:

  1. 更新数据库成功。
  2. 删除缓存成功。

不理想的情况下:

  1. 更新数据库成功。

  2. 删除缓存失败

  3. 更新数据库失败。

关于第一种不理想的情况,我们可以将要删除的key放入消息队列中,自己消费,不断重试,直到操作成功。

关于第二中不理想的情况,我们直接在应用层抛出异常就OK了。

先删除缓存,再更新数据库

最理想的情况下:

  1. 删除缓存成功。
  2. 更新数据库成功。

不理想的情况下:

  1. 删除缓存成功。

  2. 更新数据库失败。

  3. 删除缓存失败。

关于两种不理想的情况下,大多数情况下缓存和数据库的一致性都是一样的。但还是会出现不一致的情况例如下面:

  • 线程A删除了缓存
  • 线程B查询,发现缓存已不存在
  • 线程B去数据库查询得到旧值
  • 线程B将旧值写入缓存
  • 线程A将新值写入数据库

解决方法是:通过队列串行化,将删除缓存、修改数据库、读取缓存等的操作积压到队列里边,实现串行化

总结
  • 先删除缓存,再更新数据库

    • 在高并发下表现不如意,在原子性被破坏时表现优异
  • 先更新数据库,再删除缓存(Cache Aside Pattern设计模式)

    • 在高并发下表现优异,在原子性被破坏时表现不如意

为什么Redis早期版本选择使用单线程

根据官方的解释,由于Redis是基于内存的操作,因此CPU不是Redis的瓶颈,Redis的瓶颈最有可能是内存的大小容量或者网络带宽。既然单线程容易实现而且不会导致性能问题,Redis开发人员就选择采用单线程方案了。

  1. 使用单线程模型能带来更好的 可维护性,方便开发和调试;
  2. 使用单线程模型也能 并发 的处理客户端的请求;(I/O 多路复用机制)
  3. Redis 服务中运行的绝大多数操作的 性能瓶颈都不是 CPU

Redis为什么那么快

  1. 纯内存操作。
  2. 单线程,无锁竞争。
  3. 多路I/O复用技术,非堵塞IO。
  4. 高效的数据结构,底层有大量的优化。

评论