`
IXHONG
  • 浏览: 451580 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Redis客户端简单封装

阅读更多

 Redis客户端简单封装并集成spring. spring-data-redis对redis有过度封装的嫌疑,而且也没有提供sharding模式,本文遂简单封装jedis。

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
       default-autowire="byName">
    
    <!-- 单个实例 -->
    <bean id="singletonRedisClient" class="com.itlong.whatsmars.redis.client.singleton.SingletonRedisClient">
        <property name="host" value="127.0.0.1"/>
        <property name="port" value="6379" />
        <property name="maxTotal" value="256"/>
        <property name="maxIdle" value="8" />
        <property name="maxWait" value="3000" />
        <property name="timeout" value="3000" />
        <property name="minIdle" value="2" />
    </bean>
    <!-- M-S读写分离 -->
    <bean id="readWriteRedisClient" class="com.itlong.whatsmars.redis.client.readwrite.ReadWriteRedisClient">
        <property name="hosts" value="127.0.0.1:6379,127.0.0.1:7379"/>
        <property name="maxTotal" value="256"/>
        <property name="maxIdle" value="8" />
        <property name="maxWait" value="3000" />
        <property name="timeout" value="3000" />
        <property name="minIdle" value="2" />
    </bean>
    <!-- Cluster模式 -->
    <bean id="redisClusterClient" class="com.itlong.whatsmars.redis.client.cluster.RedisClusterClient">
        <property name="addresses" value="127.0.0.1:6379,127.0.01:7379,127.0.0.1:8379"/>
        <property name="maxTotal" value="256"/>
        <property name="maxIdle" value="8" />
        <property name="maxWait" value="3000" />
        <property name="timeout" value="3000" />
        <property name="minIdle" value="2" />
    </bean>

    <!-- 客户端sharding模式,待进行 -->

</beans>

 

 

 

package com.itlong.whatsmars.redis.client.singleton;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class SingletonRedisClient implements FactoryBean<JedisPool>,InitializingBean {
    private JedisPool jedisPool;

    private int maxTotal = 128;

    //最大空闲连接数
    private int maxIdle = 2;

    //最小空闲连接数
    private int minIdle = 1;
    //如果连接池耗尽,最大阻塞的时间,默认为3秒
    private long maxWait = 3000;//单位毫秒
    private String host;
    private int port;
    private int database = 0;//选择数据库,默认为0
    private int timeout = 3000;//connectionTimeout,soTimeout,默认为3秒

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String password;

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setDatabase(int database) {
        this.database = database;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        jedisPool = new JedisPool(config,host,port,timeout, password, database,null);
    }

    @Override
    public JedisPool getObject() throws Exception {
        return jedisPool;
    }

    @Override
    public Class<?> getObjectType() {
        return JedisPool.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

 

package com.itlong.whatsmars.redis.client.readwrite;

import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class ReadWriteRedisClient implements InitializingBean {
    //master:port,slave:port,slave:port...
    //master first
    private String hosts;
    private JedisPool master;
    private List<JedisPool> slaves = new ArrayList<JedisPool>();

    private int maxTotal = 128;

    //最大空闲连接数
    private int maxIdle = 2;

    //最小空闲连接数
    private int minIdle = 1;
    //如果连接池耗尽,最大阻塞的时间,默认为3秒
    private long maxWait = 3000;//单位毫秒
    private int database = 0;//选择数据库,默认为0
    private int timeout = 3000;//connectionTimeout,soTimeout,默认为3秒

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String password;

    private Random random = new Random();

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setDatabase(int database) {
        this.database = database;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setHosts(String hosts) {
        this.hosts = hosts;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        String[] hostAndPorts = hosts.split(",");
        String masterHP = hostAndPorts[0];
        String[] ms = masterHP.split(":");
        master = new JedisPool(config,ms[0],Integer.valueOf(ms[1]),timeout, password, database,null);
        if(hostAndPorts.length > 1) {
            for(int i = 1; i < hostAndPorts.length; i++) {
                String[] ss = hostAndPorts[i].split(":");
                JedisPool slave = new JedisPool(config,ss[0],Integer.valueOf(ss[1]),timeout, password, database,null);
                slaves.add(slave);
            }
        }
        slaves.add(master);
    }

    public String get(String key) {
        Jedis jedis = fetchResource(true);
        try {
            return jedis.get(key);
        } finally {
            jedis.close();
        }
    }

    public List<String> mget(String... keys) {
        Jedis jedis = fetchResource(true);
        try {
            return jedis.mget(keys);
        } finally {
            jedis.close();
        }
    }

    public String setex(String key,int seconds,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.setex(key,seconds,value);
        } finally {
            jedis.close();
        }
    }

    public Long setnx(String key,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.setnx(key,value);
        } finally {
            jedis.close();
        }
    }

    public String set(String key,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.set(key,value);
        } finally {
            jedis.close();
        }
    }

    public Long del(String key) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.del(key);
        } finally {
            jedis.close();
        }
    }

    public Long expire(String key,int seconds) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.expire(key,seconds);
        } finally {
            jedis.close();
        }
    }

    public Boolean exists(String key) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.exists(key);
        } finally {
            jedis.close();
        }
    }

    public Long exists(String... keys) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.exists(keys);
        } finally {
            jedis.close();
        }
    }

    private Jedis fetchResource(boolean read) {
        if(slaves.isEmpty() || !read) {
            return master.getResource();
        }
        int size = slaves.size();
        int i = random.nextInt(size);
        return slaves.get(i).getResource();
    }


    public static void main(String[] args) throws Exception {
        String prefix = "_test_";
        ReadWriteRedisClient client = new ReadWriteRedisClient();
        client.setHosts("127.0.0.1:6379,127.0.0.1:6379");

        client.afterPropertiesSet();

        client.set(prefix + "10001","test");
        System.out.println(client.get(prefix + "10001"));
    }
}

 

package com.itlong.whatsmars.redis.client.cluster;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class RedisClusterClient implements FactoryBean<JedisCluster>,InitializingBean {
    private JedisCluster jedisCluster;

    private int maxTotal = 128;

    //最大空闲连接数
    private int maxIdle = 6;

    //最小空闲连接数
    private int minIdle = 1;
    //如果连接池耗尽,最大阻塞的时间,默认为3秒
    private long maxWait = 3000;//单位毫秒

    private int timeout = 3000;//connectionTimeout,soTimeout,默认为3秒

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String addresses;//ip:port,ip:port

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setAddresses(String addresses) {
        this.addresses = addresses;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();

        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    private Set<HostAndPort> buildHostAndPorts() {
        String[] hostPorts = addresses.split(",");
        Set<HostAndPort> hostAndPorts = new HashSet<HostAndPort>();
        for(String item : hostPorts) {
            String[] hostPort = item.split(":");
            HostAndPort hostAndPort = new HostAndPort(hostPort[0],Integer.valueOf(hostPort[1]));
            hostAndPorts.add(hostAndPort);
        }
        return hostAndPorts;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        Set<HostAndPort> hostAndPorts = buildHostAndPorts();
        jedisCluster = new JedisCluster(hostAndPorts,timeout,config);
    }

    @Override
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    @Override
    public Class<?> getObjectType() {
        return JedisCluster.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

 

 

/**
 * Created by javahongxi on 2017/6/23.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-redis.xml")
public class Demo {

    @Autowired
    @Qualifier("singletonRedisClient")
    private JedisPool singletonRedisClient;

    @Autowired
    private ReadWriteRedisClient readWriteRedisClient;

    @Autowired
    @Qualifier("redisClusterClient")
    private JedisCluster jedisCluster;

    @Test
    public void testSingleton() {
        Jedis jedis = singletonRedisClient.getResource();
        String cacheContent = null;
        try {
            cacheContent = jedis.get("hello_world");
        }finally {
            singletonRedisClient.close();
        }
        // 获取redis数据之后,立即释放连接,然后开始进行业务处理
        if(cacheContent == null) {
            // DB operation
        }
        // ..
    }

    @Test
    public void testReadWrite() {
        String cacheContent = null;
        try {
            cacheContent = readWriteRedisClient.get("hello_world");
        } catch (Exception e) {
            //如果异常,你可以决定是否忽略
        }
        if(cacheContent == null) {
            //如果cache中不存在,或者redis异常
        }
    }

    @Test
    public void testCluster() {
        String cacheContent = null;
        try {
            cacheContent = jedisCluster.get("hello_world");
        } catch (Exception e) {
            //如果异常,你可以决定是否忽略
        }
        if(cacheContent == null) {
            //如果cache中不存在,或者redis异常
        }
    }
}

 

 

@基于M-S模式下读写分离

通常情况下,Slave只是作为数据备份,不提供read操作,这种考虑是为了避免slave提供stale数据而导致一些问题。 不过在很多场景下,即使slave数据有一定的延迟,我们仍然可以兼容或者正常处理,此时我们可以将slave提供read 服务,并在M-S集群中将read操作分流,此时我们的Redis集群将可以支撑更高的QPS。本实例中,仅仅提供了“读写分 离”的样板,尚未对所有的redis方法进行重写和封装,请开发者后续继续补充即可。此外,slave节点如果异常,我们 应该支持failover,这一部分特性后续再扩展。 

代码 https://github.com/javahongxi/whatsmars/tree/master/whatsmars-redis
0
1
分享到:
评论
2 楼 IXHONG 2017-06-27  
1.减少数据库查询,直接查缓存
2.数据预热,提前将数据放到缓存
3.解决高并发场景数据库操作延时问题,如select->insert
4.session存储
5.简单消息
6.分布式锁
7.当做nosql数据库用
masuweng 写道
说下应用场景吧,麻烦了。

1 楼 masuweng 2017-06-23  
说下应用场景吧,麻烦了。

相关推荐

    Redis客户端Java服务接口封装

    本文将围绕“Redis客户端Java服务接口封装”这一主题进行深入探讨,结合给定的`RedisClientTemplate.java`文件,我们将讨论如何在Java环境中高效地与Redis进行交互。 首先,`RedisClientTemplate`这个名字暗示它是...

    NewLife.Redis 是一个Redis客户端组件,高性能Redis协议封装,支持.Net Core

    NewLife.Redis 是一个Redis客户端组件,以高性能处理大数据实时计算为目标。Redis协议基础实现Redis/RedisClient位于X组件,本库为扩展实现,主要增加列表结构、哈希结构、队列等高级功能。

    redis客户端

    Redis客户端是用于与Redis缓存服务器进行交互的工具,它允许开发者执行命令、管理数据、监控性能以及进行数据备份和恢复。Redis是一个高性能的键值数据库,广泛应用于数据缓存、消息队列、数据持久化等多个场景。在...

    redis客户端.rar

    这些客户端库通常封装了网络通信细节,使得开发人员可以简单地调用API发送Redis命令,处理返回的结果。 压缩包中的文件“redis-desktop-manager-0.8.8.384.exe”很可能是一个图形化的Redis客户端管理工具,名为...

    基于C#的NewLife.Redis高性能Redis协议封装设计源码

    本项目是基于C#的NewLife.Redis高性能Redis协议封装设计源码,包含119个...该项目是一个高性能的Redis协议封装库,支持.Net Core,经过一年多日均80亿调用量验证,旨在为用户提供一个高效、稳定的Redis客户端解决方案。

    Redis操作字符串工具类封装,Redis工具类封装

    在`RedisPoolUtils`这个类中,我们可以看到它是对Jedis或Lettuce等Redis客户端的进一步封装,以提供更简洁、易用的操作接口。首先,我们需要引入Redis客户端的依赖,例如Jedis库: ```xml &lt;groupId&gt;redis.clients...

    Redis协议客户端模块.rar

    通过深入理解Redis协议和易语言的特性,开发者可以构建一个高效、稳定的Redis客户端模块,为应用程序提供强大的数据存储和处理能力。在实际项目中,应结合具体需求对模块进行定制和优化,确保其满足性能和功能的要求...

    simpleRedisClient:封装node js redis模块的简单Redis客户端模块

    封装node js redis模块的简单Redis客户端模块 例子: var redisClient = require('simpleRedisClient'); var client = redisClient.createClient(); 客户端连接()。然后( function () { console.log('...

    Redis协议客户端易语言模块源码

    资源介绍:。JimStone(谢栋) - Redis协议客户端模块。Redis协议客户端模块:STRedisClient for E。实现了对 Redis 客户端协议的封装。资源作者:。JimStone(谢栋)。资源界面:。资源下载:。

    RedisDB封装库

    StackExchange.Redis是一个高效、全面的Redis客户端,支持多种数据类型和操作,为.NET开发者提供了方便的接口来与Redis进行交互。下面将详细讨论RedisDB封装库的核心功能以及StackExchange.Redis库的关键特性。 ...

    redis客户端 RedisClient

    例如,在Java中,Jedis是常用的Redis客户端,提供了丰富的API供开发者调用。在Python中,redis-py是官方推荐的客户端库。这些客户端库通常会封装网络I/O操作,使开发者能够更方便地与Redis交互。 在使用RedisClient...

    redis c++封装.zip

    2. **C++客户端库**:常见的C++ Redis客户端库有`redis-plus-plus`、`hiredis`等。这些库提供了连接管理、命令发送与接收、异常处理等功能,是C++封装Redis的基础。 3. **连接管理**:封装时需包含建立连接、断开...

    redis简单封装

    1. 异步支持:对于高并发场景,可以使用异步版本的Redis客户端,如`aioredis`,利用异步IO提高性能。 2. 缓存策略:根据业务需求,实现缓存淘汰、过期策略等,如LRU(Least Recently Used)。 3. 数据一致性:处理...

    c# Redis使用及封装类

    本文将深入探讨如何在C#环境中使用Redis,并介绍一个简单的Redis封装类,帮助开发者更便捷地集成Redis到他们的项目中。 首先,安装Redis是使用它的第一步。你需要在本地或服务器上安装Redis服务,可以通过官方网站...

    redis常用方法封装

    在Java开发中,Jedis是连接Redis的客户端库,它提供了丰富的API来操作Redis的各种数据结构,如字符串、哈希、列表、集合、有序集合等。本封装主要关注了以下几个方面的内容: 1. **Jedis连接管理**: - 初始化...

    Redis 客户端:它提供了丰富的功能,如管道、集群、Lua 脚本支持等,可以方便地与 Redis 数据库进行交互

    它还封装了 Redis 命令,可以直接调用对应的 JavaScript 函数,例如 `set`, `get`, `hset`, `lpush`, `sadd`, `zadd` 等。 ```javascript client.set('key', 'value'); client.get('key', (err, value) =&gt; { // ...

    Asp.net 封装Redis帮助类

    首先,`StackExchange.Redis.dll`是.NET平台上的一个流行的Redis客户端库,它提供了一组丰富的API来与Redis服务器通信。这个库使得.NET开发者能够方便地集成Redis到他们的应用中,处理各种数据结构如字符串、列表、...

    封装StackExchange.Redis

    由于ServiceStack.Redis已经收费,所以开始转向StackExchange.Redis使用,这里不讨论性能,只是封装其使用;网上有一位网友的封装我很喜欢,逐步修改了下。把redis几种存储的操作分别封装在一个类中;分别增加了单例...

    Redis封装动态库

    2. 链接Redis客户端库:Redis通常提供了C语言的客户端库(hiredis),需要链接这个库来实现与Redis服务器的通信。例如,使用`-lhiredis`选项。 3. 动态库标志:指定生成动态库的选项,如-g生成调试信息,-shared生成...

Global site tag (gtag.js) - Google Analytics