一、Redis是什么?
Redis是一个以内存作为存储的 NoSQL 型数据库。以是C语言开发并遵从BSD协议,常见用于数据库、缓存、消息中间件等。
优点:
- 读写速度非常快:支持并发10W QPS。
- 单进程单线程:是线程安全的,采用IO多路复用机制。
- 丰富的数据类型:支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。
- 支持数据持久化:可以将内存中数据保存在磁盘中,重启时加载。
- 主从复制,哨兵,高可用。
- 作分布式。
Redis为何这么快?
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常迅速,数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度是O(1)。
- 数据结构简单,对数据操作也简单。
- 采用单线程,避免了不必要的上下文切换和竞争条件,不存在多线程导致的CPU切换,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有死锁问题导致的性能消耗。
- 使用多路复用IO模型,非阻塞IO。
二、支持的数据类型
在聊数据类型之前,我们先了解redis是如何表示数据类型的?如下图:
redis内部使用一个redisObject对象来表示所有的key和value。如上图所示:type表示一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式。
例如:type=string表示value存储的是一个普通字符串,那么encoding可以是raw或者int。
五种数据类型:
- string:以 key=>value方式存储,是二进制安全的,所以 string 类型可以包含任何数据,比如jpg图片或者序列化的对象。string 类型的值最大能存储512M。常见命令:set、get。
- Hash:hash 是一个 string 的 key 和 value 的映射表,所以特别适合存储对象。常用命令:hget、hset、hgetall等。
- list:简单的字符串列表,按照插入顺序排序。常用命令:lpush、rpush、lpop、rpop、lrange(获取列表片段)等。
- set:string类型的无序集合,通过hashtable实现的。set中的元素是没有顺序的,而且是没有重复的。常用命令:sdd、spop、smembers、sunion等。
- zset:string类型元素的集合,且不允许重复的元素。是有序的 额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。
三、redis-缓存问题
雪崩
含义:同一时间大面积 key 失效。一般特指热门数据,大范围失效,然后大量请求直接查询DB。导致数据库崩溃。
应对方法:
- 生成 key 时候有效期随机生成,避免同时过期。
- 如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效。
- 永不过期,数据更新时候更新缓存。
穿透
含义:穿透是指缓存和数据库中都没有的数据,而用户不断发起大量请求,直接查崩溃DB。一般是不合法的用户(黑客)攻击。
应付方法:
- 程序层过滤,做参数校验。
- 使用redis 布隆过滤器(Bloom Filter)。原理:利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查DB刷新KV再return。
击穿
含义:类似雪崩,不同之处在于特指一个热点 key,失效。在这个 key失效瞬间,大量的请求直接捅到数据库。所以叫缓存击穿。
应对办法:
- 数据永不过期。
四、淘汰策略
策略 | 备注 |
---|---|
volatile-lru | 从已设置过期时间的KV集中优先对最近最少使用(less recently used)的数据淘汰 |
volitile-ttl | 从已设置过期时间的KV集中优先对剩余时间短(time to live)的数据淘汰 |
volitile-random | 从已设置过期时间的KV集中随机选择数据淘汰 |
allkeys-lru | 从所有KV集中优先对最近最少使用(less recently used)的数据淘汰 |
allKeys-random | 从所有KV集中随机选择数据淘汰 |
noeviction | 不淘汰策略,若超过最大内存,返回错误信息 |
备注: 文中部分图片、文字来源网络。