使用jedis连接redis-cluster进行字符串数据结构api演示

天大地大妈咪最大 提交于 2020-01-09 04:12:52

继上一篇创建测试基类之后,可以根据父类创建子类进行专门的测试,下面将针对基于jedis连接redis cluster集群的操作做一个系列文章。本章内容讲解redis 字符串数据结构的一些jedis操作。

package com.coderman.jedis.clusterdemo;

import com.alibaba.fastjson.JSON;
import com.coderman.jedis.dto.PersonDto;
import com.coderman.jedis.serialize.ProtoStuffSerializerUtil;
import org.junit.Test;

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

/**
 * @Author fanchunshuai
 * @Date 2019/12/28 18
 * @Description:Redis的String数据结构练习
 *
 * 字符串类型的值实际可以 是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、
 * 数字 (整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能 超过512MB。
 *
 *字符串类型的内部编码有3种:
 * ·int:8个字节的长整型。
 * ·embstr:小于等于39个字节的字符串。
 * ·raw:大于39个字节的字符串。
 * Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
 * Redis没有采用原生C语言的字符串类型而是自己实现了字符串结构,内 部简单动态字符串(simple dynamic string,SDS)。
 *
 *
 * Redis自身实现的字符串结构有如下特点:
 * ·O(1)时间复杂度获取:字符串长度、已用长度、未用长度。
 * ·可用于保存字节数组,支持安全的二进制数据存储。
 * ·内部实现空间预分配机制,降低内存再分配次数。
 * ·惰性删除机制,字符串缩减后的空间不释放,作为预分配空间保留。
 *
 * https://mp.weixin.qq.com/s/3IptChwLLMN6aTeQhapSNw
 *
 */
public class StringDataAPITest extends ClusterTest {

    private static final String USER_PREFIX = "sso:user:";

    @Test
    public void testAddStr(){
        String userId = USER_PREFIX+1;
        cluster.set(userId,"樊春帅");
        String userName = cluster.get(userId);
        System.out.println("userName = "+userName);
    }

    /**
     * 修改
     */
    @Test
    public void testUpdateStr(){
        String userId = USER_PREFIX+2;
        cluster.set(userId,"樊春帅222","NX","EX",30);
        String userName = cluster.get(userId);
        System.out.println("userName = "+userName);
    }

    /**
     * json序列化
     * @throws InterruptedException
     */
    @Test
    public void testAddPersonDto() throws InterruptedException {
        PersonDto personDto = new PersonDto();
        personDto.setAge(27);
        personDto.setId(3L);
        personDto.setCard("asdfnalsnl23");
        personDto.setName("fanchunshuai");
        String userKey = USER_PREFIX+"3";
        //1.json序列化,返回值是OK,设置过期时间30s
        //nx:当键不存在时添加成功,否则失败可以用于实现分布式锁
        //ex:过期时间
        String value = cluster.set(userKey, JSON.toJSONString(personDto),"NX","EX",30);
        System.out.println("value = "+value);
        //查询
        String strPerson = cluster.get(userKey);
        System.out.println("strPerson = "+strPerson);
        //反序列化
        PersonDto personDto1 = JSON.parseObject(strPerson,PersonDto.class);
        System.out.println(JSON.toJSONString(personDto1));
        //更新过期时间,为2秒
        cluster.expire(userKey,2);
        Thread.sleep(2000);
        //再次获取
        String personExpireed = cluster.get(userKey);
        System.out.println("personExpireed = "+personExpireed);
        //xx:当键存在时更新成功,否则失败
        //ex:过期时间
        String valuex = cluster.set(userKey, JSON.toJSONString(personDto),"xx","EX",30);


    }


    /**
     * 更新
     * @throws InterruptedException
     */
    @Test
    public void testUpdatePersonDto() throws InterruptedException {
        PersonDto personDto = new PersonDto();
        personDto.setAge(27);
        personDto.setId(4L);
        personDto.setCard("asdkfasldfnkalsdfnals");
        personDto.setName("zhangsan");
        String userKey = USER_PREFIX+"4";
        //1.json序列化,返回值是OK,设置过期时间30s
        String value = cluster.set(userKey, JSON.toJSONString(personDto),"NX","EX",30);
        System.out.println("value = "+value);
        //2.覆盖
        cluster.set(userKey, "");
        String newValue = cluster.get(userKey);
        System.out.println("newValue = "+newValue);
    }


    /**
     * protobuff序列化与反序列化
     * @throws InterruptedException
     */
    @Test
    public void testPersonDtoProtoBuff() throws InterruptedException {
        PersonDto personDto = new PersonDto();
        personDto.setAge(27);
        personDto.setId(5L);
        personDto.setCard("asdkfasldfnkalsdfnals");
        personDto.setName("zhangsan");
        String userKey = USER_PREFIX+"5";
        //1.protoStuff序列化,返回值是OK,设置过期时间30s
        String value = cluster.set(userKey.getBytes(), ProtoStuffSerializerUtil.serialize(personDto),"NX".getBytes(),"EX".getBytes(),30);
        System.out.println("value = "+value);
        byte[] newValue = cluster.get(userKey.getBytes());
        System.out.println("newValue = "+ProtoStuffSerializerUtil.deserialize(newValue,PersonDto.class));
        String newKey = userKey+"1000";
        //集群模式下不支持该命令,会报错
        // No way to dispatch this command to Redis Cluster because keys have different slots.
        Long id = cluster.renamenx(userKey,newKey);
        System.out.println("id = "+id);
    }

    /**
     * 测试批量获取
     */
    @Test
    public void testMget(){

        List<String> stringList = new ArrayList<>();

        for (int i = 10; i < 1000 ; i++) {
            String key = USER_PREFIX +i;
            cluster.set(key,key);
            stringList.add(key);
        }
        String[] strings = new String[stringList.size()];

        stringList.toArray(strings);
        //集群模式不支持该api,会报错
        //No way to dispatch this command to Redis Cluster because keys have different slots.
        List<String> values = cluster.mget(strings);
        values.forEach(str->{
            System.out.println(str);
        });
    }
}

涉及到protobuff的序列化,这里引入maven坐标:

   <dependency>
      <groupId>io.protostuff</groupId>
      <artifactId>protostuff-core</artifactId>
      <version>1.5.9</version>
    </dependency>

    <dependency>
      <groupId>io.protostuff</groupId>
      <artifactId>protostuff-runtime</artifactId>
      <version>1.5.9</version>
    </dependency>

提供protobuff的工具类:

package com.coderman.jedis.serialize;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * @Author fanchunshuai
 * @Date 2019/12/28 18
 * @Description:
 */
public class ProtoStuffSerializerUtil {

    private ProtoStuffSerializerUtil() {
    }

    /**
     * 序列化单个对象
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> byte[] serialize(T obj){
        if (null == obj) {
            throw new RuntimeException("序列化对象不能为空:" + obj);
        }
        Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(obj.getClass());
        LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
        byte[] protostuff = null;
        try {
            protostuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new RuntimeException("序列化->" + obj.getClass() + "对象" + obj + "发生异常", e);
        } finally {
            buffer.clear();
        }
        return protostuff;
    }

    /**
     * 反序列化单个对象
     * @param paramArrayOfByte
     * @param targetClass
     * @param <T>
     * @return
     */
    public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
        if (null == paramArrayOfByte || paramArrayOfByte.length == 0) {
            throw new RuntimeException("反序列化对象发生异常,byte序列为空");
        }
        T instance = null;
        try {
            instance = targetClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("反序列化过程中一句类型创建对象失败", e);
        }
        Schema<T> schema = RuntimeSchema.getSchema(targetClass);
        ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
        return instance;
    }

    /**
     * 序列化对象集合(List)
     * @param objList
     * @param <T>
     * @return
     */
    public static <T> byte[] serializeList(List<T> objList) {
        if (null == objList || objList.isEmpty()) {
            throw new RuntimeException("序列化对象列表" + objList + "参数异常");
        }
        Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
        LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
        byte[] protostuff = null;
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
            protostuff = bos.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException("序列化对象列表" + objList + "发生异常", e);
        } finally {
            buffer.clear();
        }
        return protostuff;
    }

    /**
     * 反序列化对象集合(List)
     * @param <T>
     * @param paramArrayOfByte
     * @param targetClass
     * @return
     */
    public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class targetClass) {
        if (null == paramArrayOfByte || paramArrayOfByte.length == 0) {
            throw new RuntimeException("反序列化对象发生异常,byte序列为空");
        }
        Schema<T> schema = RuntimeSchema.getSchema((Class<T>) targetClass);
        List<T> result = null;
        try {
            result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);
        } catch (IOException e) {
            throw new RuntimeException("反序列化对象列表发生异常", e);
        }
        return result;
    }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!