前面有一篇文章介绍了在 windows 系统里面搭建一个 Redis 环境,环境我们都搭建好了,总不至于搭着玩玩吧,接下来就会介绍,怎么样在最基础的单机形式下使用 Redis(循序渐进嘛,毕竟还有主从、哨兵和集群的形式,一下子也说不完)

引入 Redis 的依赖

在 pom.xml 文件中加入 Redis 的依赖

springboot单机qps springboot单机并发_springboot单机qps


截图标注部分

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

配置 Redis 服务

在 application.properties 中为我们的工程配置 Redis 服务,这样在我们的工程启动以后,就会自动连接上 Redis 服务

springboot单机qps springboot单机并发_java_02


截图部分如下

#Redis
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# 连接超时时间(毫秒),时间太短可能会连接超时
spring.redis.timeout=500
## Redis服务器连接密码(默认为空)
spring.redis.password=111111
## 连接池中的最大连接数
spring.redis.poolMaxTotal=10
## 连接池中的最大空闲连接
spring.redis.poolMaxIdle=10
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.poolMaxWait=3

设置 Redis 中的 value 的序列化方式

示例代码使用的是 fastjson 做的序列化,也可使用 Jackson,方式稍微有点区别

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 设置 Redis 中 key 和 value 的序列化方式 (fastjson)
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        template.setValueSerializer(fastJsonRedisSerializer);

        template.setHashKeySerializer(new StringRedisSerializer());
        template.setKeySerializer(new StringRedisSerializer());
        return template;
    }
}

测试 Redis 内存的存取

上述工作准备完成后,就差不多可以使用了,接下来就是来一段测试代码

为了看起来整齐,对原来的 RedisTemplate 做了一层封装

@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public RedisUtils(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    //----------------- object ------------------

    public boolean expire(String key, long expireTime) {
        if (expireTime <= 0) {
            return false;
        }
        try {
            return redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        } catch (Exception e) {
            return false;
        }
    }

    public long getExpire(String key) {
        return redisTemplate.getExpire(key);
    }

    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            return false;
        }
    }

    public void delKey(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

    public Object get(String key) {
        if (StringUtil.isEmpty(key)) {
            return null;
        }
        return redisTemplate.opsForValue().get(key);
    }

    public boolean set(String key, Object obj) {
        if (StringUtil.isEmpty(key)) {
            return false;
        }

        try {
            redisTemplate.opsForValue().set(key, obj);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public boolean set(String key, Object obj, long expire) {
        if (StringUtil.isEmpty(key)) {
            return false;
        }

        try {
            redisTemplate.opsForValue().set(key, obj, expire, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

再来看看调用处的代码逻辑,里面的逻辑很简单

@RestController
@RequestMapping(Constant.URL.USER)
@Slf4j
public class UserController extends BaseController{
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserServiceImp userService;
    @Autowired
    private RoleService roleService;

    @PostMapping("/new")
    public Response addUserInfo(@RequestBody UserInfo user) {
        log.debug("addUserInfo" + JSON.toJSONString(user));
        Response ret = new Response();
        ret.setSuccess(ErrorCode.ERR_UNKNOW);
        if (user == null) {
            ret.setSuccess(ErrorCode.ERR_USER_INFO);
            return ret;
        }

        Role roleTag = new Role();
        roleTag.setId(user.getRole());
        List<Role> testSet = roleService.getRoles(roleTag);
        if (testSet == null || testSet.size() == 0) {
            ret.setSuccess(ErrorCode.ERR_ROLE_NOT_EXIST);
            return ret;
        }

        if (user.getId() != null) {
            user.setId(null);
        }
        try {
            UserInfo toRet = userService.addUserInfo(user);
            toRet.setUserPwd(Constant.PWD_2_SHOW);
            if (toRet != null) {

                boolean testFlag = redisUtils.set(Constant.URL.USER + toRet.getId(), toRet);
                System.out.println("testFlag " + testFlag);
                ret.setSuccess(ErrorCode.SUCCESS);
                ret.setContent(toRet);
                return ret;
            }
        } catch (Exception e) {
            e.printStackTrace();
            ret.setSuccess(ErrorCode.ERR_USER_DUPLICATE);
        }

        return ret;
    }

    @RequestMapping(value = "/info/{id}", method = RequestMethod.GET)
    public Response getUserInfo(@PathVariable("id") Integer id) {
//        for(int i = 0; i < 2; i++) {
//            hoshMQSender.send("不知道是什么鬼的测试内容" + i);
//        }
        Object test = redisUtils.get(Constant.URL.USER + id);
        System.out.printf("getUserInfo " + JSON.toJSONString(test));

        log.debug("getUserInfo {}", id);
        UserInfo toRet = userService.getUserInfoById(id);
        toRet.setUserPwd(Constant.PWD_2_SHOW);
        Response ret = new Response();
        ret.setSuccess(ErrorCode.SUCCESS);
        ret.setContent(toRet);
        return ret;
    }
}

把程序跑起来,可以得到下面的测试结果

springboot单机qps springboot单机并发_spring boot_03

总结

测试代码的测试逻辑是,先插入一条数据,插入数据成功后,将插入的数据使用 Redis 存起来,查询的时候,先去 Redis 里面查询,再去 MySql 查询。这样的搭配比较符合一般的使用逻辑,Redis 的数据是存在内存中,查询速度比存在 IO 操作的 MySql 快;所以, Redis 用于存储热数据,主要指经常被使用的数据,从而,避免瞬时的高并发请求,使得数据库扛不住;MySql 则是存储全部的数据,两者相互协作