Spring Boot 使用 Pika 集群使用的正确姿势

上周有同事过来求助,他申请了pika集群,进行接入结果监控发现只有一个集群上连接数很大,其他集群上连接数没几个,连接偏移了。他写的代码我这边就不贴了,1.安全问题,2.知识产权问题,3.防止对大家产生误导。这里只写接入的正确姿势。

先说说pika是啥,是奇虎公司(即大家熟悉的360公司)开源的基于Redis通讯协议的基于硬盘存储高速缓存。github地址:https://github.com/OpenAtomFoundation/pika 。所以大家接入的时候,使用spring boot 集成的 redis jar包即可。pika是单节点的,没有集群,所以分片的路由规则需要自己写。

前面是铺垫,下面进入正题,首先这位同事申请的是5个节点。

1、添加的maven 引用

                    org.springframework.boot            spring-boot-starter-data-redis                                    redis.clients            jedis            4.2.3        

2、在 application.properties 添加配置

pika.database=0pika.pool.maxActive=8pika.pool.maxIdle=8pika.pool.minIdle=1pika.pool.maxWait=5000pika.pool.testOnBorrow=falsepika.pool.blockWhenExhausted=truepika.timeout=60000pika.pika0.host=ip0pika.pika0.password=mima0pika.pika0.port=8096pika.pika1.host=ip1pika.pika1.password=mima1pika.pika1.port=8096pika.pika2.host=ip2pika.pika2.password=mima2pika.pika2.port=8096pika.pika3.host=ip3pika.pika3.password=mima3pika.pika3.port=8096pika.pika4.host=ip4pika.pika4.password=mima4pika.pika4.port=8096

3.添加 PikaClusterConfig 配置类

@Slf4j@Configurationpublic class PikaClusterConfig {    /**     * pika连接池最大连接数     */    @Value("${pika.pool.maxActive}")    private int pikaPoolMaxActive;    /**     * pika连接池最大空闲     */    @Value("${pika.pool.maxIdle}")    private int pikaPoolMaxIdle;    /**     * pika连接池最小空闲     */    @Value("${pika.pool.minIdle}")    private int pikaPoolMinIdle;    /**     * pika获取连接时的最大等待时间     */    @Value("${pika.pool.maxWait}")    private long pikaPoolMaxWait;    /**     * pika拿取链接时测试是否成功     */    @Value("${pika.pool.testOnBorrow}")    private boolean pikaPoolTestOnBorrow;    /**     * 用尽报错     */    @Value("${pika.pool.blockWhenExhausted}")    private boolean pikaPoolBlockWhenExhausted;    /**     * pika连接超时时间,单位毫秒.60×1000     */    @Value("${pika.timeout}")    private long pikaTimeout;    @Bean(name = "redisTemplate0")    public RedisTemplate redisTemplate0(@Value("${pika.pika0.host}") String hostName,                                              @Value("${pika.pika0.port}") int port,                                              @Value("${pika.pika0.password}") String password) {        StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory(hostName, port, password));        return initSerializer(template);    }    @Bean(name = "redisTemplate1")    public RedisTemplate redisTemplate1(@Value("${pika.pika1.host}") String hostName,                                              @Value("${pika.pika1.port}") int port,                                              @Value("${pika.pika1.password}") String password) {        StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory(hostName, port, password));        return initSerializer(template);    }    @Bean(name = "redisTemplate2")    public RedisTemplate redisTemplate2(@Value("${pika.pika2.host}") String hostName,                                              @Value("${pika.pika2.port}") int port,                                              @Value("${pika.pika2.password}") String password) {        StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory(hostName, port, password));        return initSerializer(template);    }    @Bean(name = "redisTemplate3")    public RedisTemplate redisTemplate3(@Value("${pika.pika3.host}") String hostName,                                              @Value("${pika.pika3.port}") int port,                                              @Value("${pika.pika3.password}") String password) {        StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory(hostName, port, password));        return initSerializer(template);    }    @Bean(name = "redisTemplate4")    public RedisTemplate redisTemplate4(@Value("${pika.pika4.host}") String hostName,                                              @Value("${pika.pika4.port}") int port,                                              @Value("${pika.pika4.password}") String password) {        StringRedisTemplate template = new StringRedisTemplate(jedisConnectionFactory(hostName, port, password));        return initSerializer(template);    }    private RedisTemplate initSerializer(StringRedisTemplate template) {        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();        template.setKeySerializer(stringRedisSerializer);        template.setValueSerializer(stringRedisSerializer);        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();        template.setHashKeySerializer(jackson2JsonRedisSerializer);        template.setHashValueSerializer(jackson2JsonRedisSerializer);        return template;    }    /**     * 获取redis连接池     *     * @param hostName     * @param port     * @param password     * @return     */    private JedisConnectionFactory jedisConnectionFactory(String hostName, int port, String password) {        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();        standaloneConfig.setHostName(hostName);        standaloneConfig.setPort(port);        if (!StringUtils.isEmpty(password)) {            standaloneConfig.setPassword(password);        }        //standaloneConfig.setDatabase(pikaDatabase);        //连接池配置        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();        genericObjectPoolConfig.setMaxIdle(pikaPoolMaxIdle);        genericObjectPoolConfig.setMinIdle(pikaPoolMinIdle);        genericObjectPoolConfig.setMaxTotal(pikaPoolMaxActive);        genericObjectPoolConfig.setMaxWaitMillis(pikaPoolMaxWait);        genericObjectPoolConfig.setBlockWhenExhausted(pikaPoolBlockWhenExhausted);        genericObjectPoolConfig.setTestOnBorrow(pikaPoolTestOnBorrow);        //client配置        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()                .connectTimeout(Duration.ofMillis(pikaTimeout))                .readTimeout(Duration.ofMillis(pikaTimeout))                .usePooling().poolConfig(genericObjectPoolConfig)                .build();        //返回连接池        JedisConnectionFactory factory = new JedisConnectionFactory(standaloneConfig, clientConfig);        factory.afterPropertiesSet();        return factory;    }}

4.添加 PikaService 根据主键获取RedisTemplate

@Servicepublic class PikaService {    @Qualifier("redisTemplate0")    @Autowired    private RedisTemplate redisTemplate0;    @Qualifier("redisTemplate1")    @Autowired    private RedisTemplate redisTemplate1;    @Qualifier("redisTemplate2")    @Autowired    private RedisTemplate redisTemplate2;    @Qualifier("redisTemplate3")    @Autowired    private RedisTemplate redisTemplate3;    @Qualifier("redisTemplate4")    @Autowired    private RedisTemplate redisTemplate4;    public  RedisTemplate shardRedisTemplate(String key) {        int index = Math.abs(key.hashCode() % 5);        // replace Math.abs(key.hashCode()) % REDIS_TEMPLATES.size() 因存在问题:hashCode=Integer.MIN_VALUE时仍为负数        switch (index) {            case 0:                return redisTemplate0;            case 1:                return redisTemplate1;            case 2:                return redisTemplate2;            case 3:                return redisTemplate3;            case 4:                return redisTemplate4;            default:                return null;        }    }}

好了,核心的代码添加完毕了。

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章