什么是 Redis?
Redis (Remote Dictionary Server 远程字典服务) 是一个开源的使用 ANSI C 语言编写,支持网络,可基于内存亦可持久化的日志型,key-value 数据库,提供多种语言的 API。
Redis 有哪些常用功能?
- 数据缓存
- 数据持久化
- 支持事务
- 消息队列
- 分布式锁
小Q:Redis 有哪些数据类型?
- String:Redis 最基础的数据结构。
- Hash:一种键值对的结构,其相对于字符串序列化结构更加直观,并且在更新操作上更加便捷。(底层是 ziplist 或 hashtable)
- List:基于双向链表,可以充当栈和队列的角色。(底层是 ziplist 或 linkedlist)
- Set:用来保证集合中不能有重复元素。(底层是 intset 或 hashtable)
- zset:有序集合,类似于 treeSet,它保留了 set 不能有重复元素外,还将集合里的元素进行排序。(底层是 skiplist)
小Q:什么是 ziplist?
慢慢:ziplist 是由一系列特殊编码的,连续内存快组成的顺序存储结构,类似于数组。ziplist 在内存中是连续的,所以每次插入时,都会重新 malloc 空间,保证其连续性。一般情况下在数据量小的时候使用。
小Q:Redis 有哪些使用场景?
慢慢:redis 的应用很广泛。
- 缓存:减轻 MYSQL 的查询压力,提升系统性能;
- 排行榜:利用 Redis 的 zset 实现;
- 计算器/限速器:利用 redis 中原子性的自增操作,我们可以统计类似用户点赞、用户访问数等。这类操作如果用 MYSQL,频繁的读写会带来相当大的压力,限速器比较典型的使用场景是限制某个用户访问某个 API 的频率,常用的有抢购时,防止用户疯狂点击开来不必要的压力;
- 好友关系:利用集合的一些命令,如交集,并集,差集等,可以方便实现一些共同好友,共同爱好之类的功能;
- 消息队列:除了 Redis 自身的发布/订阅模式,我们也可以利用 List 来实现一个队列机制。
小Q:Redis 如何解决 hash 冲突?
慢慢:Redis 采用链地址法解决 hash 冲突。即一个桶里面的元素使用链表保持。但当链表过长时就会导致性能变差。Redis 为了追求快,使用了两个全局哈希表,用于 rehash 操作。
小Q:rehash(扩容) 的具体操作
- 开始时默认使用 hash table1 保持键值对数据,hash table2 没有分配空间。
- 当数据越来越多,就会触发 rehash 操作。
- 给 hash table2 分配 hash table1 多一倍的空间。
- 将 hash1 的数据重映射到 hash2 中
- 释放 hash1 的空间。
重映射的过长不是一次性的,因为这也会造成 redis 长时间阻塞,无法提供服务。它采用渐进式 rehash,每次处理客户端请求的时候,会先从 hash table1 中找到对应的桶,将桶里面的数据移动到 hash table2 中,这样就将 rehash 操作分散到多次请求中,避免耗时阻塞。