redis 学习笔记(7)-cluster 客户端(jedis)代码示例

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 上节学习了cluster的搭建及redis-cli终端下如何操作,但是更常用的场景是在程序代码里对cluster读写,这需要redis-client对cluster模式的支持,目前spring-data-redis(1.

上节学习了cluster的搭建及redis-cli终端下如何操作,但是更常用的场景是在程序代码里对cluster读写,这需要redis-client对cluster模式的支持,目前spring-data-redis(1.6.4)还不支持cluster,最新的1.7.0 RC1已经有cluster的相关实现了,不过目前尚未正式发布,所以现阶段要使用redis-cluster的话,client最好还是选用原生的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.xsd">


    <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg index="0">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="7000"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="7001"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="127.0.0.1"/>
                    <constructor-arg name="port" value="7002"/>
                </bean>
                <!--<bean class="redis.clients.jedis.HostAndPort">-->
                    <!--<constructor-arg name="host" value="127.0.0.1"/>-->
                    <!--<constructor-arg name="port" value="7003"/>-->
                <!--</bean>-->
                <!--<bean class="redis.clients.jedis.HostAndPort">-->
                    <!--<constructor-arg name="host" value="127.0.0.1"/>-->
                    <!--<constructor-arg name="port" value="7004"/>-->
                <!--</bean>-->
                <!--<bean class="redis.clients.jedis.HostAndPort">-->
                    <!--<constructor-arg name="host" value="127.0.0.1"/>-->
                    <!--<constructor-arg name="port" value="7005"/>-->
                <!--</bean>-->
            </set>
        </constructor-arg>
    </bean>
</beans>

注:上面的这些节点,不需要配全,最少可以只保留一个cluster中的节点信息,运行时,jedis会自动发现其它节点,但是为了防止某个节点挂掉,所以建议配置时,还是多配置几个,保证这一堆节点中,至少有一个能连接上。

示例代码:

package com.cnblogs.yjmyzz.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

import java.util.List;
import java.util.Map;
import java.util.Set;


public class AppDemo {

    private static Logger logger = LoggerFactory.getLogger(AppDemo.class);
    private static JedisCluster jc = null;

    private static final String KEYS_STRING = "STRING";
    private static final String KEYS_SET = "SET";
    private static final String KEYS_LIST = "LIST";
    private static final String KEYS_HASH = "HASH";
    private static final String KEYS_ZSET = "ZSET";


    private static void addKey(final String conainter, final String key) {
        if (!jc.exists(conainter)) {
            jc.sadd(conainter, key);
        } else {
            if (!jc.smembers(conainter).contains(key)) {
                jc.sadd(conainter, key);
            }
        }
    }

    /**
     * 写入字符串缓存
     *
     * @param key
     * @param value
     * @return
     */
    private static String set(final String key, final String value) {
        String result = jc.set(key, value);
        addKey(KEYS_STRING, key);
        return result;
    }

    /**
     * 写入Set缓存
     *
     * @param key
     * @param member
     * @return
     */
    private static Long sadd(final String key, final String... member) {
        Long result = jc.sadd(key, member);
        addKey(KEYS_SET, key);
        return result;
    }


    /**
     * 从左侧写入List
     *
     * @param key
     * @param string
     * @return
     */
    private static Long lpush(final String key, final String... string) {
        Long result = jc.lpush(key, string);
        addKey(KEYS_LIST, key);
        return result;
    }


    /**
     * 写入HashMap缓存
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    private static Long hset(final String key, final String field, final String value) {
        Long result = jc.hset(key, field, value);
        addKey(KEYS_HASH, key);
        return result;
    }


    /**
     * 写入ZSet缓存
     *
     * @param key
     * @param score
     * @param member
     * @return
     */
    private static Long zadd(final String key, final double score, final String member) {
        Long result = jc.zadd(key, score, member);
        addKey(KEYS_ZSET, key);
        return result;
    }

    private static Long zadd(final String key, final String member) {
        Long result = jc.zadd(key, 0d, member);
        addKey(KEYS_ZSET, key);
        return result;
    }


    public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-redis.xml");

        jc = ctx.getBean(JedisCluster.class);


        Map<String, JedisPool> nodes = jc.getClusterNodes();
        for (Map.Entry<String, JedisPool> entry : nodes.entrySet()) {
            logger.info(entry.getKey() + " => " + entry.getValue().toString());
            //清空所有数据
            try {
                entry.getValue().getResource().flushDB();
            } catch (Exception e) {
                logger.info(e.getLocalizedMessage());//slave节点上执行flushDB会报错
            }
            //entry.getValue().getResource().keys("*");//慎用,缓存数量较大时,会引起性能问题.
        }

        //检测key是否存在
        logger.info(jc.exists("a").toString());

        //字符串写入测试
        logger.info(set("a", "hello world!"));
        logger.info(set("b", "hello redis!"));

        //字符串读取测试
        logger.info(jc.get("a"));

        //set写入操作
        logger.info("set写入测试 ==>");
        logger.info(sadd("set1", "a", "b", "c") + "");

        //缓存类型测试
        logger.info(jc.type("set1"));

        //set读取测试
        logger.info("set读取测试 ==>");
        Set<String> set1 = jc.smembers("set1");
        for (String s : set1) {
            logger.info(s);
        }

        //list写入测试
        logger.info("list写入测试 ==>");
        logger.info(lpush("list1", "1", "2", "3") + "");


        //list读取测试
        logger.info("list读取测试 ==>");
        List<String> list1 = jc.lrange("list1", 0, 999);
        for (String s : list1) {
            logger.info(s);
        }

        //hash写入测试
        logger.info("hash写入测试 ==>");
        logger.info(hset("hash1", "jimmy", "杨俊明") + "");
        logger.info(hset("hash1", "CN", "中国") + "");
        logger.info(hset("hash1", "US", "美国") + "");

        //hash读取测试
        logger.info("hash读取测试 ==>");
        Map<String, String> hash1 = jc.hgetAll("hash1");
        for (Map.Entry<String, String> entry : hash1.entrySet()) {
            logger.info(entry.getKey() + ":" + entry.getValue());
        }

        //zset写入测试
        logger.info("zset写入测试 ==>");
        logger.info(zadd("zset1", "3") + "");
        logger.info(zadd("zset1", "2") + "");
        logger.info(zadd("zset1", "1") + "");
        logger.info(zadd("zset1", "4") + "");
        logger.info(zadd("zset1", "5") + "");
        logger.info(zadd("zset1", "6") + "");

        //zset读取测试
        logger.info("zset读取测试 ==>");
        Set<String> zset1 = jc.zrange("zset1", 0, 999);
        for (String s : zset1) {
            logger.info(s);
        }

        //遍历所有缓存项的key
        logger.info("遍历cluster中的所有key ==>");
        logger.info(jc.smembers(KEYS_STRING).toString());
        logger.info(jc.smembers(KEYS_HASH).toString());
        logger.info(jc.smembers(KEYS_SET).toString());
        logger.info(jc.smembers(KEYS_LIST).toString());
        logger.info(jc.smembers(KEYS_ZSET).toString());

    }
}

注:建议尽量避免用jedis对节点做keys的模糊搜索,该操作在缓存项较多时,可能会导致redis性能急剧下降,改进办法是自己弄一个集合,记录所有缓存的key,具体可参考上面的办法。此外,jedis提供的命令非常之多,但是没有详细的说明文档(估计,作者认为代码就是最好的文档),大体可以从方法前缀猜测出来,比如sXXX表示是对Set的操作,hXXX表示是对hash的操作,lXXX或rXXX是对list的操作,zXXX是对zset的操作,什么前缀都没有的,比如set/get是对字符串的操作。

有网友把jedis的操作整理了一份文档,请参见:http://blog.csdn.net/zhu_xun/article/details/16806285  

最后,附加上文中示例的源码:https://github.com/yjmyzz/redis-cluster-demo

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
NoSQL Redis 数据安全/隐私保护
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
文章提供了Redis最流行的图形化界面工具Another Redis Desktop Manager的下载及使用教程,包括如何下载、解压、连接Redis服务器以及使用控制台和查看数据类型详细信息。
175 6
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
|
2月前
|
NoSQL Redis 数据库
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
文章提供了Redis图形化界面工具的下载及使用教程,包括如何连接本地Redis服务器、操作键值对、查看日志和使用命令行等功能。
174 0
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
|
2月前
|
NoSQL 数据可视化 Linux
redis学习四、可视化操作工具链接 centos redis,付费Redis Desktop Manager和免费Another Redis DeskTop Manager下载、安装
本文介绍了Redis的两个可视化管理工具:付费的Redis Desktop Manager和免费的Another Redis DeskTop Manager,包括它们的下载、安装和使用方法,以及在使用Another Redis DeskTop Manager连接Redis时可能遇到的问题和解决方案。
151 1
redis学习四、可视化操作工具链接 centos redis,付费Redis Desktop Manager和免费Another Redis DeskTop Manager下载、安装
|
2月前
|
NoSQL 网络协议 算法
Redis 客户端连接
10月更文挑战第21天
38 1
|
2月前
|
NoSQL Linux Redis
Docker学习二(Centos):Docker安装并运行redis(成功运行)
这篇文章介绍了在CentOS系统上使用Docker安装并运行Redis数据库的详细步骤,包括拉取Redis镜像、创建挂载目录、下载配置文件、修改配置以及使用Docker命令运行Redis容器,并检查运行状态和使用Navicat连接Redis。
330 3
|
2月前
|
存储 消息中间件 NoSQL
Redis 入门 - C#.NET Core客户端库六种选择
Redis 入门 - C#.NET Core客户端库六种选择
69 8
|
3月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
2月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
|
2月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
39 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
2月前
|
存储 Prometheus NoSQL
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
34 3
下一篇
DataWorks