Redis - 浅谈Redis 以及 如何使用SpringDataRedis对数据进行缓存?

一、浅谈Redis?

1.为什么要用Redis?

前台系统中:    如用户访问的效率特别低 -> 用户体验差 -> 用户的粘稠低 -> 失去用户!

不常用的数据: 如果从mysql中查询 -> 放到数据磁盘上 -> (如用户访问量大)频繁进行I/O操作
                       造成硬件过热 -> 增加mysql的吞吐量 -> mysql性能降低 -> db层性能降低
                       -> app性能降低 -> 用户体验差!

如何解决该问题?
                       不进行I/O操作  ->  数据放在内存中就可以  ->  故用redis来操作.

 
当然除了redis,还有memcache , ssdb ( 内存数据库 )

  • memcache: 纯的内存数据库 , 不能进行持久化 , 数据结构比较单一.
                        ( 只有String类型 )
  • ssdb: 想取代Redis , 一般是Redis(读) + ssdb(写) 组合使用( lua脚本 )
             共用一套接口api!

2.Redis是什么?

              Redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化Key-Value数据库。

redis的特点:
         1.高性能.   官方数据: 读的速度是110000次/s,写的速度是81000次/s 。
         2.持久存储.
         3.适应高并发.

3.redis支持的五种数据类型。

  • 1.String字符串: Map<String , String>
  • 2.List链表 : Map<String , LinkedList
  • 3.set集合 : Map<String , hashSet>
  • 4.zset(sorted set – 有序集合):
  • 5.hash哈希类型: Map<String , hash<String,String>>

4.Redis持久化:

1、RDB:默认—快照   每隔一段时间将数据持久化一次
策略:        时间   改变的次数
         save   900   1 // 如果900秒内 , 有1个key发生改变持久化一次.
         save   300   10 // 如果300秒内 , 有10个key发生改变持久化一次.
         save   60     10000 // 如果60秒内 , 有10000个key发生改变持久化一次.

好处:增量备份---文件小
缺点:容易出现数据丢失   

2、AOF:相当日志 ( 默认:关闭 ) 记录写操作!
     xxx.aof文件中内容( 文件-大 )
格式:记录命令

例:  set name 'tom'
	 set school 'beijing'
	 $6 select 
	 $1 0
	 $3 set 
 	 $4 name 
	 $3 tom 
	 $n : 该命令的字符个数. 
	 0: redis一共16号库 , 默认的数据存储在0号库. 

5.可能遇到的问题?

  • 缓存穿透:
                   并发访问时(多个人同时访问判空?) —> 都去db中查询!
    解决:
            1.请求排队等候 ( synchronized(this) )
            2.二次校验. ( 再次进行判断缓存中有没有? )

  • 缓存雪崩:
                    服务器崩溃 / 缓存失效 !
    解决:
            缓存降级 ( 将一些数据提前放到缓存中 )
            注: 但数据不一定完整 或者 是实时的数据!

二、SpringDataRedis

1.SpringDataRedis概述?

            Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis,JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。 spring-data-redis针对jedis提供了如下功能:
 
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
                  String-ValueOperations:简单K-V操作
                  Set-SetOperations:set类型数据操作
                  Zset-ZSetOperations:zset类型数据操作
                  hash-HashOperations:针对map类型的数据操作
                  list-ListOperations:针对list类型的数据操作

2.SpringDataRedis的优点?

1、对jedis的高度封装
2、使用开发人员对redis的操作更简单
3、对数据进行序列化。

3.案例: 使用SpringDataRedis对首页广告轮播图添加缓存.

1.添加连接redis服务的配置文件: redis-config.properties

redis.host=192.168.200.128 
redis.port=6379 
redis.pass=
redis.database=0 
redis.maxIdle=300 
redis.maxWait=3000
redis.testOnBorrow=true

2.添加SpringDataRedis配置文件: applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<context:property-placeholder location="classpath*:properties/*.properties" />
	<!-- redis 相关配置 -->
	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWait}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
	</bean>
	<bean id="JedisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
		p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
		p:pool-config-ref="poolConfig" />

	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="JedisConnectionFactory" />
	</bean>
</beans>

3.service实现类进行缓存添加.
问题? 使用redis哪种数据结构?

String类型: set key(广告分类id) value(查询到的广告结果集)            注: key-value : 需要查询多次!
Hash类型: hset key filed value                                                          注: 只查询一次!
 
而我们使用redis优化:
                                  就是要减少与数据库的交互的次数!

@Override
public List<Content> findByCategoryId(Long categoryId) {
   // 判断缓存是否有
   List<Content> list = (List<Content>) redisTemplate.boundHashOps("content").get(categoryId);
   if(list == null){
	synchronized (this) {
	      list = (List<Content>) redisTemplate.boundHashOps("content").get(categoryId);
	      if(list == null){
		   // 从数据库中查询
		   ContentQuery contentQuery = new ContentQuery();
		   contentQuery.createCriteria().andCategoryIdEqualTo(categoryId).andStatusEqualTo("1");
		   list = contentDao.selectByExample(contentQuery);
		   // 将数据放入缓存
		   redisTemplate.boundHashOps("content").put(categoryId, list);
	      }
	}
   }
   return list;
}
发布了107 篇原创文章 · 获赞 173 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42986107/article/details/85252618