redis总结
1.什么是redic.
redis是一个非关系数据库,我们项目中主要用它来存储热点数据的,减轻数据库的压力.
存热点数据,临时数据,之前集中式存session的数据现在都用redis存储。Redis是使用c语言开发的一个开源的高性能键值对(key-value)数据库。Redis是将数据存放到内存中,由于内容存取速度快所以redis被广泛应用在互联网项目中。
2.为啥用redis.
因为当访问量特别大的时候,直接从数据库获取信息内容会造成数据库压力过大,所以像访问量特别大的热点数据我们都放到缓存中,从缓存中获取,加快查询速度,提高系统性能。
3.咋用redis.
配置环境,先安装redis,spring data是一个用于简化数据库访问的开源框架,主要目标是使得对数据库的访问变得更加方便快捷,其中,我们使用spring data redis 配置访问redis。
导入依赖 spring-boot-starter-data-redis 在配置文件中配置号ip端口,或者集群,连接池最大连接数,最大空闲连接,最小空闲连接。
Spring data redis为我们提供了redistemplate,直接注入就可以操作redis,非常简单,为了简化开发,还配置了redis工具类,用来处理序列化和反序列化,还可以再写一个封装redistemplate的工具类,可以直接使用原生的redis指令来操作redis变的更加简单。
4.redis的数据类型.
redis呢有5种数据类型,String、list、hash、set、zset,常用的就是String,list,hash.
一些简单的key-value类型的都存储在string类型中,首页的推荐数据和热门数据都用hash来存。
5.redis持久化.
redis还有两种持久化方式,一个是RDB,这也是redis默认的持久化方式,这种方式是以快照的方式存储数据,在固定的时间段内如果有多少变化,那么就会生成快照存储到磁盘上,redis 在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。在redis.conf配置文件中默认有此下配置:
save 900 1 #900秒内容如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000 #表示60秒内如果超过10000个key被修改,则发起快照保存.
还有一种是AOF,是即时性的持久化方式,是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。AOF的方式会导致性能下降。
默认情况下Redis没有开启AOF(append onlyfile)方式的持久化,可以通过appendonly参数开启:appendonly yes。
AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof,可以通过appendfilename参数修改:appendfilename appendonly.aof
6.主从赋值.
主可以读可以写,从只能读。
持久化保证了即使redis服务重启也会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障
过程:
slave 服务启动,slave 会建立和master 的连接,发送sync 命令。
master启动一个后台进程将数据库快照保存到RDB文件中
master 就发送RDB文件给slave
slave 将文件保存到磁盘上,然后加载到内存恢复
master把缓存的命令转发给slave
7.集群的搭建.
所有reids节点彼此互联(ping-pong机制)
节点的fail是通过集群中超过半数的节点检测失效时才生效
集群中有一个节点fail,则整个集群都会fail
Redis-cluster把所有物理节点映射到0-16383slot上,内置了16384个哈希槽,当需 要 在redis集群中放置一个key-value时,redis先对key进行才crc16运算,把结果对16384求余数,每个key都会对应一个哈希槽,根据节点数量映射到不同的节点
Reids集群中至少应该有3个节点。要保证集群的高可用,需要每个节点有一个备份机。
集群主要来处理高并发的问题,当数据量大,访问量大的时候需要搭建集群。
- redis缓存商品信息方案
使用redis做缓存,业务逻辑:
1、根据商品id到redis中查询
查得到,直接返回
2、查不到,查询mysql,
数据放到redis中
设置缓存的有效期一天的时间,可以根据实际情况调整。
- 缓存穿透
描述:
缓存穿透是指缓存和数据库中都没有数据,而用户不断发起请求则这些请求会穿过缓存直接访问数据库,如发起为id为“-1”的数据或id为特别大不存在的数据。(redis中没有这个数据了,比如说缓存时间到了)假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。
解决方案:
缓存空对象:
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间(避免控制占用更多的存储空间),之后再访问这个数据将会从缓存中获取,保护了后端数据源;
- 缓存击穿
描述
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个key不停进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案
解决方案:
- 设置热点数据永远不过期
- 加分布式锁
redis分布式锁
这个分布式锁这里,我们原来传统的项目都在单台服务器上部署用java里的锁synchronized这个同步锁就行,但是他这个是针对对象的锁,但是我们分布式的项目需要把项目部署到多台服务器上,每台服务器的对象都不同,所以就得考虑用分布式锁,这块实现起来也比较简单,其实这个锁就是redis中的一个key-value的一对值,在使用的时候,首先使用setnx方法进行尝试加锁,并可以设置过期时间,如果返回1则代表加锁成功,然后立即对这个锁设置一个实效时间,防止服务宕机,锁一致存在,在处理完业务逻辑之后,删除锁就行了,其他线程就可以获取锁进行业务了.
/**
* 分布式锁
* @param key
* @param count
* @param value
* @return
*/
public Boolean setnx(String key, Object value, long time) {
try {
return redisTemplate.opsForValue().setIfAbsent(key, value, time,
TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
--------------------------------------------我是分割线-------------------------------------------------------
//1、先查询redis,如果有直接返回
TbItem tbItem = (TbItem) redisClient.get(ITEM_INFO+":"+itemId+":"+BASE);
if(tbItem!=null){
return tbItem;
}
/**解决缓存击穿/
if(redisClient.setnx(SETNX_BASC_LOCK_KEY+":"+itemId,itemId,30L)){
//2、再查询mysql,并把查询结果缓存到redis,并设置失效时间
tbItem = tbItemMapper.selectByPrimaryKey(itemId);
/*****************解决缓存穿透*****************/
if(tbItem!=null){
redisClient.set(ITEM_INFO+":"+itemId+":"+BASE,tbItem);
redisClient.expire(ITEM_INFO+":"+itemId+":"+BASE,ITEM_INFO_EXPIRE);
}else{
redisClient.set(ITEM_INFO+":"+itemId+":"+BASE,null);
redisClient.expire(ITEM_INFO+":"+itemId+":"+BASE,30L);
}
redisClient.del(SETNX_BASC_LOCK_KEY+":"+itemId);
return tbItem;
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return selectItemInfo(itemId);
}
}
- 缓存雪崩
描述:
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
解决方案:
缓存数据的过期时间设置随机或不同分类商品缓存不同周期或热门类目的商品缓存永不过期

浙公网安备 33010602011771号