Springboot與Redis Cache深度整合

目錄

  1. Springboot項目創建
  2. Springboot與Redis整合
  3. Springboot與Mybatis整合
  4. Springboot與Cache整合使用
  5. Redis作爲mybatis二級緩存
  6. Redis分佈式session共享

Springboot項目創建

1.打開IDEA 創建工程

在這裏插入圖片描述

2.選擇IDEA中Spring initilazier
在這裏插入圖片描述

3.設置自己的包命名規範
在這裏插入圖片描述

4.勾選Web -> Spring Web -> Next -> Finish創建工程
在這裏插入圖片描述
5.創建對應的文件夾,後面內容基於此文件夾進行配置,工程結構
在這裏插入圖片描述

Springboot與Redis整合

1.打開pom.xml,引入依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.再application.yml配置

spring:
  redis:
    port: 6379
    host: xxx.xxx.xx.xx

3.再config文件夾下創建RedisConfig.java 進行redisTemplate初步調用

package com.gcxzflgl.redis.config;


/**
 * @author gcxzf$
 * @version : RedisConfiguration$, v 0.1 2020/6/13$ 15:39$ gcxzf$ Exp$
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,String> restTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }
}

4.編寫測試案例測試redisTemplate保存到redis中

package com.gcxzflgl.redis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class RedisApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("gcx","is handsonn boy");
    }

}

5.查看redis中存在測試用例的key,因爲我們暫未配置序列化方式,使用的是默認JdkSerializationRedisSerializer序列化方式,後面會逐步配置自己能看懂的序列化方式
在這裏插入圖片描述

Springboot與Mybatis整合

1.再pom.xml中添加mybatis相關依賴

<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>5.1.47</version>
 </dependency>
 <dependency>
     <groupId>org.mybatis.spring.boot</groupId>
     <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>1.3.0</version>
 </dependency>

 <dependency>
     <groupId>org.mybatis.generator</groupId>
     <artifactId>mybatis-generator-core</artifactId>
     <scope>test</scope>
     <version>1.3.2</version>
     <optional>true</optional>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-jdbc</artifactId>
 </dependency>

 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.1.10</version>
 </dependency>

 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.7</version>
 </dependency>

2.再application.yml中配置如下

spring:
  datasource:
    url: jdbc:mysql://xxx.xxx.xx.xx:3306/redis?useUnicode=true&characterEncoding=UTF-8
    username: xxx           # 需要修改填寫
    password: xxxxx         # 需要修改填寫
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    minIdle: 5
    maxActive: 100
    initialSize: 10
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 50
    removeAbandoned: true
    filters: stat # ,wall,log4j # 配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用於防火牆
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
    useGlobalDataSourceStat: true # 合併多個DruidDataSource的監控數據
    druidLoginName: gcx # 登錄druid的賬號
    druidPassword: gcx # 登錄druid的密碼
    cachePrepStmts: true  # 開啓二級緩存
mybatis:
  typeAliasesPackage: com.gcxzflgl.redis.mapper      # 需要修改填寫
  mapperLocations: classpath:/mapper/*.xml
  mapperScanPackage: com.gcxzflgl.redis.mapper
  configLocation: classpath:/mybatis-config.xml

3.再resources下新建mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE configuration  
     PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
     "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
	    <!-- 使全局的映射器啓用或禁用緩存。 -->
		<setting name="cacheEnabled" value="true" />
		<!-- 全局啓用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載。 -->
		<setting name="lazyLoadingEnabled" value="true" />
		<!-- 當啓用時,有延遲加載屬性的對象在被調用時將會完全加載任意屬性。否則,每種屬性將會按需要加載。 -->        
         <setting name="aggressiveLazyLoading" value="true"/>        
         <!-- 是否允許單條sql 返回多個數據集  (取決於驅動的兼容性) default:true -->
		<setting name="multipleResultSetsEnabled" value="true" />
		<!-- 是否可以使用列的別名 (取決於驅動的兼容性) default:true -->
		<setting name="useColumnLabel" value="true" />
		<!-- 允許JDBC 生成主鍵。需要驅動器支持。如果設爲了true,這個設置將強制使用被生成的主鍵,有一些驅動器不兼容不過仍然可以執行。  default:false  -->
		<setting name="useGeneratedKeys" value="false" />
		<!-- 指定 MyBatis 如何自動映射 數據基表的列 NONE:不隱射 PARTIAL:部分  FULL:全部  -->
		<setting name="autoMappingBehavior" value="PARTIAL" />
		<!-- 這是默認的執行類型  (SIMPLE: 簡單; REUSE: 執行器可能重複使用prepared statements語句;BATCH: 執行器可以重複執行語句和批量更新)  -->
		<setting name="defaultExecutorType" value="SIMPLE" />
		
		<setting name="defaultStatementTimeout" value="25" />
		
		<setting name="defaultFetchSize" value="100" />
		
		<setting name="safeRowBoundsEnabled" value="false" />
		<!-- 使用駝峯命名法轉換字段。 -->
		<setting name="mapUnderscoreToCamelCase" value="true" />
		<!-- 設置本地緩存範圍 session:就會有數據的共享  statement:語句範圍 (這樣就不會有數據的共享 ) defalut:session -->
		<setting name="localCacheScope" value="SESSION" />
		<!-- 默認爲OTHER,爲了解決oracle插入null報錯的問題要設置爲NULL -->
		<setting name="jdbcTypeForNull" value="NULL" />
		<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
	</settings>
	
</configuration>


4.再config包下創建DataSourceConfig.java配置文件注入sql相關

package com.gcxzflgl.redis.config;




/**
 * Created by wanlichao on 2016/10/25 0025.
 */

@Configuration
@MapperScan("com.gcxzflgl.redis.mapper")
public class DataSourceConfig {
    private Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);

    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Value("${spring.datasource.type}")
    private String dbType;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.initialSize}")
    private int initialSize;

    @Value("${spring.datasource.minIdle}")
    private int minIdle;

    @Value("${spring.datasource.maxActive}")
    private int maxActive;

    @Value("${spring.datasource.maxWait}")
    private int maxWait;

    @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.validationQuery}")
    private String validationQuery;

    @Value("${spring.datasource.testWhileIdle}")
    private boolean testWhileIdle;

    @Value("${spring.datasource.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.testOnReturn}")
    private boolean testOnReturn;

    @Value("${spring.datasource.poolPreparedStatements}")
    private boolean poolPreparedStatements;

    @Value("${spring.datasource.filters}")
    private String filters;

    @Value("${spring.datasource.connectionProperties}")
    private String connectionProperties;

    @Value("${spring.datasource.useGlobalDataSourceStat}")
    private boolean useGlobalDataSourceStat;

    @Value("${spring.datasource.druidLoginName}")
    private String druidLoginName;

    @Value("${spring.datasource.druidPassword}")
    private String druidPassword;



    @Bean(name="dataSource")
    @Primary //不要漏了這
    public DataSource dataSource(){
        DruidDataSource datasource = new DruidDataSource();
        try {
            datasource.setUrl(this.dbUrl);
            datasource.setDbType(dbType);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);
            datasource.setInitialSize(initialSize);
            datasource.setMinIdle(minIdle);
            datasource.setMaxActive(maxActive);
            datasource.setMaxWait(maxWait);
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            datasource.setValidationQuery(validationQuery);
            datasource.setTestWhileIdle(testWhileIdle);
            datasource.setTestOnBorrow(testOnBorrow);
            datasource.setTestOnReturn(testOnReturn);
            datasource.setPoolPreparedStatements(poolPreparedStatements);
            datasource.setFilters(filters);
        } catch (SQLException e) {
            logger.error("druid configuration initialization filter", e);
        }
        return datasource;
    }

    /////////  下面是druid 監控訪問的設置  /////////////////
    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean reg = new ServletRegistrationBean();
        reg.setServlet(new StatViewServlet());
        reg.addUrlMappings("/druid/*");  //url 匹配
        reg.addInitParameter("allow", "192.168.16.110,127.0.0.1"); // IP白名單 (沒有配置或者爲空,則允許所有訪問)
        reg.addInitParameter("deny", "192.168.16.111"); //IP黑名單 (存在共同時,deny優先於allow)
        reg.addInitParameter("loginUsername", this.druidLoginName);//登錄名
        reg.addInitParameter("loginPassword", this.druidPassword);//登錄密碼
        reg.addInitParameter("resetEnable", "false"); // 禁用HTML頁面上的“Reset All”功能
        return reg;
    }

    @Bean(name="druidWebStatFilter")
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); //忽略資源
        filterRegistrationBean.addInitParameter("profileEnable", "true");
        filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
        filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
        return filterRegistrationBean;
    }
}

5.創建sql腳本

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `sys_user`
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', '高晨曦');
INSERT INTO `sys_user` VALUES ('2', '瑞燊兒');

6.再domain包下新建實體

package com.gcxzflgl.redis.domain;

import java.io.Serializable;

public class User implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = -4415438719697624729L;


    private String id;

    private String userName;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }


    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

7.再mapper包中創建mapper映射類

package com.gcxzflgl.redis.mapper;

import com.gcxzflgl.redis.domain.User;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Component;

import java.util.List;

@Mapper
@Component
public interface UserMapper {

	@Insert("insert sys_user(id,user_name) values(#{id},#{userName})")
	void insert(User u);
	
	@Update("update sys_user set user_name = #{userName} where id=#{id} ")
	void update(User u);
	
	@Delete("delete from sys_user where id=#{id} ")
	void delete(@Param("id") String id);

	@Select("select id,user_name from sys_user where id=#{id} ")
	User find(@Param("id") String id);

	//注:方法名和要UserMapper.xml中的id一致
	List<User> query(@Param("userName") String userName);

	@Delete("delete from sys_user")
	void deleteAll();
}

對應的resource/mapper下創建UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.gcxzflgl.redis.mapper.UserMapper">
 
<select id="query"  resultType="com.gcxzflgl.redis.domain.User">
    select id ,user_name 
    from sys_user 
    where 1=1
    <if test="userName != null">
      and user_name like CONCAT('%',#{userName},'%')
    </if>
</select>
</mapper>

8.再service層引入業務方法類UserService

package com.gcxzflgl.redis.biz;


/**
 * @author gcxzf$
 * @version : UserService$, v 0.1 2020/6/13$ 15:16$ gcxzf$ Exp$
 */
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
 

    /**
     * 查找user
     * @param id
     * @return
     */
    public User find(String id){     
        User users = userMapper.find(id); 
        return users;  
    }
}

9.再rest報下創建UserController

package com.gcxzflgl.redis.rest;


/**
 * @author gcxzf$
 * @version : UserController$, v 0.1 2020/6/13$ 15:12$ gcxzf$ Exp$
 */

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 查找指定user
     * @param id
     * @return
     */
    @GetMapping("/find")
    public User find(@RequestParam(value = "id",required = true) String id){
        return userService.find(id);
    }
}

10.啓動項目訪問:http://xxx.xxx.xx.xx:8080/find?id=1
在這裏插入圖片描述

Springboot與Cache整合使用

SpringCache 常用註解

@Cacheable(查) 來劃分可緩存的方法 - 即,結果存儲在緩存中的方法,以便在後續調用(具有相同的參數)時,返回緩存中的值而不必實際執行該方法
@CachePut(修改、增加) 當需要更新緩存而不干擾方法執行時,可以使用@CachePut註釋。也就是說,始終執行該方法並將其結果放入緩存中(根據@CachePut選項)
@CacheEvict(刪除) : 對於從緩存中刪除陳舊或未使用的數據非常有用,指示緩存範圍內的驅逐是否需要執行而不僅僅是一個條目驅逐

改造現有代碼:

1.再pom.xml引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2.再啓動類RedisApplication.java中開啓cache緩存註解@EnableCaching

package com.gcxzflgl.redis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class RedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class, args);
    }

}

3.改造userservice類
首先再UserService類上添加註解 @CacheConfig(cacheNames = “userCache”) 此類的cache緩存名稱統一userCache開頭
再find方法中添加註解 @Cacheable(key = “#p0”,unless = “#result == null”) key = "#p0"代表緩存的key格式:userCache::id 作爲緩存key,unless 代表如果查詢結果返回null不進行緩存
完整代碼如下:

package com.gcxzflgl.redis.biz;



/**
 * @author gcxzf$
 * @version : UserService$, v 0.1 2020/6/13$ 15:16$ gcxzf$ Exp$
 */
@Service
@CacheConfig(cacheNames = "userCache")
public class UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 查找user
     * @param id
     * @return
     */
    @Cacheable(key = "#p0",unless = "#result == null")
    public User find(String id){
        User user = userMapper.find(id);
        System.out.println("緩存中不存在user");
        return user;
    }
}

4.重啓項目測試,查看緩存是否存在
訪問地址:http://xxx.xxx.xx.xx:8080/find?id=1
在這裏插入圖片描述
5.其餘緩存註解大同小異,本文不再演示

Redis作爲mybatis二級緩存

先引申一個問題:springboot cache 存在什麼問題,
第一,生成key過於簡單,容易衝突userCache::1
第二,無法設置過期時間,默認過期時間爲永久不過期
第三,配置序列化方式,默認的是序列化JDKSerialazable

爲了解決這個問題,我們再次改造工程代碼

1.自定義KeyGenerator,本文采用(類名+方法名做唯一性區分)
2.自定義cacheManager,設置緩存過期時間
3.自定義序列化方式,Jackson
再RedisConfig中配置如下代碼:

1.再config包下RedisCofig.java新增方法

/**
     * 使用類名+方法名作爲緩存key
     * @return
     */
    @Bean
    public KeyGenerator simpleKeyGenerator() {
        return (o, method, objects) -> {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(o.getClass().getSimpleName());
            stringBuilder.append(".");
            stringBuilder.append(method.getName());
            stringBuilder.append("[");
            for (Object obj : objects) {
                stringBuilder.append(obj.toString());
            }
            stringBuilder.append("]");

            return stringBuilder.toString();
        };
    }

    /**
     * 設置cache緩存過期時間
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                this.getRedisCacheConfigurationWithTtl(600), // 默認策略,未配置的 key 會使用這個
                this.getRedisCacheConfigurationMap() // 指定 key 策略
        );
    }

    /**
     * 給指定類型的key設置過期時間
     * @return
     */
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        //指定cache頭名稱爲UserInfoList的方法緩存過期時間爲100s
        redisCacheConfigurationMap.put("UserInfoList", this.getRedisCacheConfigurationWithTtl(100));
         //指定cache頭名稱爲UserInfoListAnother的方法緩存過期時間爲100s
        redisCacheConfigurationMap.put("UserInfoListAnother", this.getRedisCacheConfigurationWithTtl(18000));

        return redisCacheConfigurationMap;
    }

	/**
     * 設置過期時間,並指定序列化方式爲Jackson
     * @param seconds
     * @return
     */
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));

        return redisCacheConfiguration;
    }
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));

        return redisCacheConfiguration;
    }

2.配置以上策略後,需要再UserService類中的find方法上指定緩存策略改造如下:

package com.gcxzflgl.redis.biz;

import com.gcxzflgl.redis.domain.User;
import com.gcxzflgl.redis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;


/**
 * @author gcxzf$
 * @version : UserService$, v 0.1 2020/6/13$ 15:16$ gcxzf$ Exp$
 */
@Service
@CacheConfig(cacheNames = "userCache")
public class UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 查找user
     * @param id
     * @return
     */
//    @Cacheable(key = "#p0",unless = "#result == null")
    @Cacheable(value = "UserInfoList", keyGenerator = "simpleKeyGenerator") // @Cacheable 會先查詢緩存,如果緩存中存在,則不執行方法
    public User find(String id){
        User user = userMapper.find(id);
        System.out.println("緩存中不存在user");
        return user;
    }
}

3.再次重啓項目測試驗證方法
訪問地址:http://xxx.xxx.xx.xx:8080/find?id=1
在這裏插入圖片描述

4.測試驗證redis緩存和數據庫進行對比
準備條件:
1)再userservice中複製一個find方法不配置註解,只是方便演示,controller同理:

/**
     * 查找user(noCache)
     * @param id
     * @return
     */
    public User findNoCache(String id){
        User user = userMapper.find(id);
        return user;
    }
  /**
     * 查找user(noCache)
     * @param id
     * @return
     */
    @GetMapping("/findNoCache")
    public User findNoCache(@RequestParam(value = "id",required = true) String id){
        return userService.findNoCache(id);
    }

)2.Linux上安裝測試工具 apache abtest

abtest的安裝
1)yum install -y httpd-tools
2)ab -V檢驗是否安裝成功

驗證地址:
ab -n1000 -c10 http://xxx.xxx.xx.xx:8080/findNoCache?id=2
ab -n1000 -c10 http://xxx.xx.xx.xx:8080/find?id=2

參數說明:
1)-n:進行http請求的總個數
2)-c:請求的client個數,也就是請求併發數
3) 統計qps:qps即每秒併發數,request per second

測試案例:

10個併發情況下1000請求執行參數(沒用緩存)

[root@redis-master src]# ab -n1000 -c10 http://192.168.124.3:8080/findNoCache?id=2
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.124.3 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        
Server Hostname:        192.168.124.3
Server Port:            8080

Document Path:          /findNoCache?id=2
Document Length:        33 bytes

Concurrency Level:      10
Time taken for tests:   8.282 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      138000 bytes
HTML transferred:       33000 bytes
Requests per second:    120.75 [#/sec] (mean) (qps結果)
Time per request:       82.819 [ms] (mean)
Time per request:       8.282 [ms] (mean, across all concurrent requests)
Transfer rate:          16.27 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   75 700.0      1    7018
Processing:     1    3   2.8      3      40
Waiting:        0    3   2.8      3      39
Total:          2   78 700.0      4    7022

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      5
  75%      6
  80%      6
  90%      7
  95%      8
  98%     20
  99%   7016
 100%   7022 (longest request)

10個併發情況下1000請求執行參數(使用緩存)

[root@redis-master src]# ab -n1000 -c10 http://192.168.124.3:8080/find?id=2
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.124.3 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        
Server Hostname:        192.168.124.3
Server Port:            8080

Document Path:          /find?id=2
Document Length:        33 bytes

Concurrency Level:      10
Time taken for tests:   1.565 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      138000 bytes
HTML transferred:       33000 bytes
Requests per second:    638.99 [#/sec] (mean) (qps結果)
Time per request:       15.650 [ms] (mean)
Time per request:       1.565 [ms] (mean, across all concurrent requests)
Transfer rate:          86.11 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    7  70.6      2    1003
Processing:     1    3   1.0      3       9
Waiting:        1    3   0.9      3       8
Total:          1   10  70.5      5    1005

Percentage of the requests served within a certain time (ms)
  50%      5
  66%      5
  75%      6
  80%      6
  90%      6
  95%      7
  98%      8
  99%     10
 100%   1005 (longest request)

其他測試條件:

10個併發的情況下 1000請求 redis qps:963.85[#/sec] (mean) DB qps: 766.75 [#/sec] (mean)
100個併發的情況下 1000請求 redis qps:1130.60 [#/sec] (mean) DB qps:956.15 [#/sec] (mean)
100個併發的情況下10000請求 redsi qps: 2102.39 [#/sec] (mean) DB qps: 679.07 [#/sec] (mean)
500個併發的情況下 10000請求 redis qps:374.91 [#/sec] (mean) DB qps:扛不住

Redis分佈式session共享

1、cookie與session
1) Cookie是什麼? Cookie 是一小段文本信息,伴隨着用戶請求和頁面在 Web 服務器和瀏覽器之間傳遞。Cookie 包含每次用戶訪問站點時 Web 應用程序都可以讀取的信息,我們可以看到在服務器寫的cookie,會通過響應頭Set-Cookie的方式寫入到瀏覽器

2)HTTP協議是無狀態的,並非TCP一樣進行三次握手,對於一個瀏覽器發出的多次請求,WEB服務器無法區分是不是來源於同一個瀏覽器。所以服務器爲了區分這個過程會通過一個
sessionid來區分請求,而這個sessionid是怎麼發送給服務端的呢。cookie相對用戶是不可見的,用來保存這個sessionid是最好不過了

1.再pom.xml引入依賴

 <dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
 </dependency>

2.再RedisConfig.java類上添加註解,指定過期時間50s

@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 50)

3.再rest包下新增SessionController,重啓工程測試

package com.gcxzflgl.redis.rest;

@RestController
public class SessionController {

    @RequestMapping(value = "/setSession", method = RequestMethod.GET)
    public Map<String, Object> setSession (HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        request.getSession().setAttribute("request Url", request.getRequestURL());
        map.put("request Url", request.getRequestURL());
        return map;
    }

    @RequestMapping(value = "/getSession", method = RequestMethod.GET)
    public Object getSession (HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        map.put("sessionIdUrl",request.getSession().getAttribute("request Url"));
        map.put("sessionId", request.getSession().getId());
        return map;
    }
}

3 .用谷歌和火狐瀏覽器進行驗證
谷歌在這裏插入圖片描述
火狐
在這裏插入圖片描述
查看結果 (再次刷新session時間從新累計50s進行倒計時)
在這裏插入圖片描述

至此,基本的使用講解列舉完畢!

下章更新Redis實時排行榜!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章