Fork me on GitHub

Redis专题

Redis 专题

1. 为什么要用 redis 而不用 map/guava 做缓存,Redis 跟 Memcached 的区别

  1. 因为缓存分为本地缓存和分布式缓存,map/guava 属于本地缓存,Redis/Memcached 属于分布式缓存。
  2. 本地缓存特点:轻量、快速,生命周期随 JVM 销毁而结束;在多实例下,每个实例保存着独立的缓存,相互不一致。
  3. 分布式缓存特点:在多实例下,各实例共用一份缓存,具有一致性;要维护分布式服务高可用,程序架构复杂。

Redis 与 Memcached 区别:

  1. Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 是单线程,多路 IO 复用的网络模型。

  2. Memcached 只支持 String 类型;Redis 支持更丰富的数据类型(主要五种,String、hash、list、set、zset)。

    [官网] It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes with radius queries and streams

  3. Memcached 将数据全部存在内存中;Redis 支持数据的持久化。

  4. Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;Redis 是原生支持 Cluster 模式的。

2. 如何解决 Redis 的并发竞争 Key 问题

并发竞争key问题,主要是并发写的问题
有五种解决方案:

  1. 使用 redis 自带的 incr 命令:

    • incr 和 expire 操作用 lua 脚本执行,保证原子性,代码实现
    • 如果有其他原子性命令需求,可以通过 lua 脚本自己创建。

    [官网]Redis guarantees that a script is executed in an atomic way: no other script or Redis command will be executed while a script is being executed. This semantic is similar to the one of MULTI / EXEC

  2. 使用独占锁的方式,实现复杂,成本较高。

  3. 使用乐观锁的方式,使用 watch 监视键是否被修改。

  4. 针对客户端使用,在代码中对 redis 操作时,针对同一 key 的资源要先加锁。

  5. 利用 redis 的 setnx 实现内置的锁。

推荐阅读:Redis 的并发竞争问题的解决方案总结

3. 设置 key 的过期时间

1
2
3
4
5
6
7
8
redis> SET key yes
OK
redis> EXPIREAT key 1550469300
(integer) 1
redis> GET key
"yes" // 未超时
redis> GET key
(nil) // 超时

4. Redis 的用途小结

1

  1. 用作缓存。
  2. 排行榜,使用 SortSet 数据结构。
  3. 计数器,使用 Redis 中原子性的自增操作;限速器,限制某用户访问某 API 的频率。
  4. 好友关系,利用集合中交集、并集、差集的操作。
  5. 简单消息队列,可以使用 Redis 的订阅/发布模式,或者 List 来实现。
  6. Session 共享

不适合 Redis 的地方:

  1. 使用 Redis 去保存用户的基本信息,因为其持久化方案并不能保持数据绝对的落地,而且持久化频率若过高可能会降低 Redis 的效率。
  2. 数据量太大,数据访问频率较低的场合不适合使用 Redis,因为这些数据一直放在内存中会造成资源的浪费。

5. Redis 的有序集合主要由跳表来实现

[理解]跳表:对于单链表而言,线性查找的时间复杂度很高,是 O(n)。从链表中每隔几个结点提取出一层索引,可以在索引的基础上继续提取一层索引,如此下去直到索引中只有少数几个结点(比如只留两个结点),这种做法的时间复杂度是 O(logN),空间复杂度是 O(N)。时间复杂度与二分法、红黑树相当。

跳表的插入和删除的时间复杂度也是 O(logN)。当插入过多而不更新索引时,跳表的效率会降低,所以需要进行“平衡性”的维护,这里用到了随机函数的做法。使用随机函数,来决定将这个结点插入到哪几级索引中。

Redis 中为什么采用跳表,而不是红黑树:

  1. Redis主要操作有:插入、删除、查找、按区间查找、迭代输出。
  2. 除了按区间查找外,其他几项跳表与红黑树都能完成,而且时间复杂度一致。
  3. 按区间查找,红黑树效率不如跳表。

6. Spring 配置 Redis 注解缓存

【一定要看这篇博客!!!超牛批】spring配置redis注解缓存spring+redis的集成,redis做缓存

-------------The End-------------