redis
redis
是一个开源数据的 kv 数据库,它的数据放置于内存当中,常用来做缓存服务器。
安装
安装
//下载
wget <http://download.redis.io/releases/redis-5.0.8.tar.gz>
安装目录/usr/local/redis
//解压
tar -zxf xx
make
// 执行make install进行Redis安装
make install
//为了方便管理,将Redis文件中的conf配置文件和常用命令移动到统一文件中
mkdir bin etc
mv redis.conf /usr/local/redis/etc/
mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-server /usr/local/redis/bin/
// 启动
redis-server
// 设置绑定ip
vim /etc/redis.conf
bind xxx
// 设置后台启动redis
vim redis.conf
daemonized yes
// 查看redis进程
netstat -tunpl|grep 6379
// 链接redis客户端
redis-cli
使用 yum 安装
//需要安装Remi的软件源
yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
//然后可以使用下面的命令安装最新版本的redis
yum --enablerepo=remi install redis
//安装完毕后,即可使用下面的命令启动redis服务
service redis start
或者
systemctl start redis
特点
- 速度快,因为数据在内存当中,类似于 HashMap
- 支持丰富的数据类型,string, list, set, hash
- 支持事物,操作都是原子性的
- 丰富的特性,应用场景广泛
应用场景
缓存
因为 redis 的读取性能优异,每秒可以处理超过 10w 次的读写操作。redis 可以保存多种数据结构,单个 value 的最大限制是 1GB,而 memcached 只能保存1md的数据。
分布式锁
因为 redis 单线程的特点,对于高并发系统,都是用多服务器部署,在进行逻辑处理的时候可以用到分布式锁来限制程序的并发。
自动过期
redis 针对数据都可以设置过期时间,可以自动清理过期数据,常见的应用场景:短信验证码,活动开始和截止日期等。
秒杀的缓存层
可以利用 redis 单线程的特性来控制并发,将 redis 作为缓存平台,由于其读写能力强,不易产生程序阻塞现象。
发布订阅
可以使用 redis 的发布订阅模式实现一些聊天系统。
redis 问题
缓存雪崩
缓存雪崩,是指缓存中设置了大批量相同过期时间的数据同时过期失效,而在这一刻访问量剧增,缓存近乎失效,所有请求全部转向 DB,DB 瞬时压力过重雪崩,甚至 down 机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
- 过期时间设置随机,防止同一时间大量数据过期现象发生。
- 若 redis 缓存是分布式部署,可以把热点数据均匀分布在不同缓存数据库中。
- 均匀设置过期时间,避免同一时期过期
- 互斥锁,保证同一时间只有一个应用在构建缓存。
- 双 key 策略,主 key 设置过期时间,备 key 永久,主 key 过期,返回备 key 的内容。
- 后台更新缓存,定时更新,消息队列通知更新
缓存穿透
缓存穿透是指查询一个缓存和数据库中都没有的数据,由于大部分缓存策略是被动加载的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。用户不断发起请求,在流量大时,就可能对 DB 形成巨大的压力,利用不存在的 key 频繁攻击应用也是很大的问题。
- 缓存和数据库中都不存在的数据,可以将此 key 对应的 value 设置为一个默认的值,比如 “NULL”,并设置一个缓存的失效时间,这时在缓存失效之前,所有通过此 key 的访问都被缓存挡住了。后面如果此 key 对应的数据在 DB 中存在时,缓存失效之后,通过此 key 再去访问数据,就能拿到新的 value 了。
- 接口层增加校验,比如用户鉴权校验,id 根据数据场景做基础校验,id<=0 的直接拦截。
- 使用布隆过滤器判断数据是否存在
缓存击穿
缓存击穿是指缓存中的一个热点 Key(比如一个秒杀商品),在某个时间点过期的时候,恰好在这个时间点访问量剧增,对这个 Key 有大量的并发请求过来,请求发现缓存过期一般都会从后端 DB 加载数据并回设回缓存,但就在缓存中的数据还没有完全从 DB 中加载过来的这个时间段期间,并发瞬间造成大量请求直接击穿到 DB,对 DB 形成巨大压力。
缓存击穿,又叫热点 key 问题,是这三个问题中最经典的一个问题。
- 互斥锁
- 热点数据不设置过期时间,由后台主动更新
缓存雪崩和缓存击穿的区别
缓存击穿跟缓存雪崩类似,区别就是缓存雪崩是群体失效(多个 key),缓存击穿是单体失效(一个热点 key)。
Redis 的过期策略和内存淘汰机制
过期策略
定期删除
定期删除指的是Redis默认每隔100ms就随机抽取一些设置了过期时间的key,检测这些key是否过期,如果过期了就将其删掉。
因为key太多,如果全盘扫描所有的key会非常耗性能,所以是随机抽取一些key来删除。这样就有可能删除不完,需要惰性删除配合。
惰性删除
惰性删除不再是Redis去主动删除,而是在客户端要获取某个key的时候,Redis会先去检测一下这个key是否已经过期,如果没有过期则返回给客户端,如果已经过期了,那么Redis会删除这个key,不会返回给客户端。
所以惰性删除可以解决一些过期了,但没被定期删除随机抽取到的key。但有些过期的key既没有被随机抽取,也没有被客户端访问,就会一直保留在数据库,占用内存,长期下去可能会导致内存耗尽。所以Redis提供了内存淘汰机制来解决这个问题。
内存淘汰机制
Redis在使用内存达到某个阈值(通过maxmemory配置)的时候,就会触发内存淘汰机制,选取一些key来删除。内存淘汰有许多策略,下面分别介绍这几种不同的策略。
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。默认策略
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。