Redis的使用方法
(
命令行安装redis
1 wget http://download.redis.id/releases/redis-5.0.7.tar.gz
2 tar xf redis-5.0.7.tar.gx
3 cd redis-5.0.7
4 vi README.md
5 make
6 yum install gcc -y (安装后遇到cc command not found 时)
7 make distclean
8 make
(接下来就是安装)
9 make PREFEX =/opt/bigdata/redis5 install
10 vi /etc/profile
…export REDIS HOME=/opt/bigdata/redis5
…export PATH=$PATH:$REDIS_HOME/bin
source /etc/profile
(启动)
cd utils
./install_service.sh
service redis_6379 status
)
1.首先redis有五种类型(String ,List,hash,set,zset),它是二进制安全的
Redis中 String是可以修改的,称为动态字符串(Simple Dynamic String SDS ) 字符串内部更像是ArrayList 。
Redis 内存分配机制:字符串长度小于1MB时每次扩容都是加倍现有的空间,大于1MB时每次会扩展1MB空间。字符串最大长度是512MB
Redis 提供了两种持久化方式:RDB(默认) 和AOF
RDB:
rdb是Redis DataBase缩写
功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数
每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作
aof写入保存:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
刚刚上面你有提到redis通讯协议(RESP ),能解释下什么是RESP?有什么特点?
RESP 是redis客户端和服务端之前使用的一种通讯协议;
RESP 的特点:实现简单、快速解析、可读性好
缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
- Redis挂掉了,请求全部走数据库。
- 对缓存数据设置相同的过期时间,导致某段时间内缓存失效,请求全部走数据库。
- 很可能就把我们的数据库搞垮,导致整个服务瘫痪!
- 解决方法:在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
- 对于“Redis挂掉了,请求全部走数据库”这种情况,我们可以有以下的思路:
- 事发前:实现Redis的高可用(主从架构+Sentinel 或者Redis Cluster),尽量避免Redis挂掉这种情况发生。
- 事发中:万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)
- 事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。
什么是缓存穿透?
但是可能有黑客想把我的数据库搞垮,每次请求的ID都是负数。这会导致我的缓存就没用了,请求全部都找数据库去了,但数据库也没有这个值啊,所以每次都返回空出去。
缓存穿透是指查询一个一定不存在的数据。由于缓存不命中,并且出于容错考虑,如果从数据库查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。
解决缓存穿透也有两种方案:
- 由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器(BloomFilter)或者压缩filter提前拦截,不合法就不让这个请求到数据库层!
- 当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。
- 这种情况我们一般会将空对象设置一个较短的过期时间。
缓存更新操作
执行更新操作时,通常有两种选择:
- 先操作数据库,再操作缓存
- 先操作缓存,再操作数据库
要明确的是,无论我们选择哪个,我们都希望这两个操作要么同时成功,要么同时失败。所以,这会演变成一个分布式事务的问题。
所以,如果原子性被破坏了,可能会有以下的情况:
- 操作数据库成功了,操作缓存失败了。
- 操作缓存成功了,操作数据库失败了。
Redis的好处
1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
2) 支持丰富数据类型,支持string,list,set,Zset,hash等
3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
Redis与memcache区别
存储方式: Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。
数据支持类型: Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。
使用底层模型不同:它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
Redis是单进程单线程的,redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值
Redis集群
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
Mysql中有2000w数据,Redis中有20w数据,Redis中如何保证里面的数据都是热点数据?
Redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
Redis做异步队列
一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
如果对方追问可不可以不用sleep呢?
list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
如果对方追问能不能生产一次消费多次呢?
使用pub/sub主题订阅者模式,可以实现1:N的消息队列。
如果对方追问pub/sub有什么缺点?
在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RabbitMQ等。
如果对方追问redis如何实现延时队列?
使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理