Tair的基本使用

目录

目录

1、KV类型接口

2、Prefix类型

2.1 Tair中的Prefix 和 Redis中的 hash 的区别

3、计数器类型

4、List列表类型

5、Set集合类型

6、Map散列类型

7、Hash类型

8、Map 与 Hash的联系与区别


1、KV类型接口

基本数据类型,存储key->value 的映射,key的length小于1k,value的size小于10KB

2、Prefix类型

存储类型为pkey + skey => value,

我们可以存一组以pkey为主key,skey为子key的数据,这组数据拥有相同前缀,它们在磁盘上连续存放

接口

行为

demo

prefixPut

写入一个以pkey为主的key,一组skey

example.prefixPut("user_", "123", "Alice");

example.prefixPut("user_", "456", "Bob");

学生id -> value学生名字

prefixGet

获取某个主key下的若干子Key的值

String user123 = example.prefixGet("user_", "123");

获取 user_123 的value学生名字

getRange

给一个Key的区间,获取这个区间内所有的skey和对应的value

Map rangeData = example.getRange("user_100", "user_999");

获取 user中学生id大于100小于999的kv 组合

getRangeKey

给一个Key的区间,只获取这个区间内所有的skey

String[] rangeKeys = example.getRangeKey("user_100", "user_999");

同上,只要key

getRangeValue

给一个Key的区间,只获取这个区间内所有的skey对应的value

String[] rangeValues = example.getRangeValue("user_100", "user_999");

同上,只要value

import java.util.HashMap;
import java.util.Map;

public class Example {
    private Map storage = new HashMap<>();

    // 存储带有前缀的数据
    public void prefixPut(String prefix, String key, String value) {
        String prefixedKey = prefix + key;
        storage.put(prefixedKey, value);
    }

    // 根据前缀和键获取数据
    public String prefixGet(String prefix, String key) {
        String prefixedKey = prefix + key;
        return storage.get(prefixedKey);
    }

    // 获取范围内的键值对
    public Map getRange(String startKey, String endKey) {
        Map result = new HashMap<>();
        for (String key : storage.keySet()) {
            if (key.compareTo(startKey) >= 0 && key.compareTo(endKey) <= 0) {
                result.put(key, storage.get(key));
            }
        }
        return result;
    }

   // 获取范围内的键
    public String[] getRangeKey(String startKey, String endKey) {
        List keysInRange = new ArrayList<>();
        for (String key : storage.keySet()) {
            if (key.compareTo(startKey) >= 0 && key.compareTo(endKey) <= 0) {
                keysInRange.add(key);
            }
        }
        return keysInRange.toArray(new String[0]);
    }

    // 获取范围内的值
    public String[] getRangeValue(String startKey, String endKey) {
        List valuesInRange = new ArrayList<>();
        for (String key : storage.keySet()) {
            if (key.compareTo(startKey) >= 0 && key.compareTo(endKey) <= 0) {
                valuesInRange.add(storage.get(key));
            }
        }
        return valuesInRange.toArray(new String[0]);
    }


    public static void main(String[] args) {
        Example example = new Example();
        example.prefixPut("user_", "123", "Alice");
        example.prefixPut("user_", "456", "Bob");

        String user123 = example.prefixGet("user_", "123");
        System.out.println("User 123: " + user123);

        Map rangeData = example.getRange("user_100", "user_999");
        System.out.println("Range Data: " + rangeData);


        String[] rangeKeys = example.getRangeKey("user_100", "user_999");
        String[] rangeValues = example.getRangeValue("user_100", "user_999");

        System.out.println("Range Keys: ");
        for (String key : rangeKeys) {
            System.out.println(key);
        }

        System.out.println("Range Values: ");
        for (String value : rangeValues) {
            System.out.println(value);
        }
    }
}

2.1 Tair中的Prefix 和 Redis中的 hash 的区别

  1. 数据结构:

    • Tair的prefixPut是一种将多个键值对存储在一个桶(Bucket)中的机制。这个桶可以理解为一个存储区域,包含了以相同前缀的键值对,这样的设计可以提高存储效率和检索速度。
    • Redis的hset是哈希(Hash)数据结构中的一种操作。哈希是一个键值对的集合,每个键都与多个字段和对应的值相关联。
  2. 适用场景:

    • prefixPut适合需要高效地存储和检索以相同前缀的多个键值对的场景,例如用户属性或配置项。
    • hset适用于将相关字段和值组织在一个地方,以便于检索和管理,例如存储用户的个人信息。
  3. 键名的关系:

    • prefixPut中,多个键名有相同的前缀,这个前缀用来将它们关联到同一个桶中。
    • hset中,多个字段是属于同一个哈希的,这个哈希通过一个键名来标识。
  4. 用途:

    • prefixPut用于优化存储效率和检索速度,特别是当有许多相关键值对需要存储时,避免数据碎片。
    • hset用于存储多个字段和对应的值,便于组织和检索复杂的数据,适用于哈希结构。
  5. 操作复杂度:

    • prefixPut涉及将多个键值对组织到一个桶中,通常更适用于批量操作,但可能需要考虑桶内数据的平衡。
    • hset更适用于单个字段和值的操作,对单个字段的读写是O(1)的常数时间,但在一些情况下,哈希结构可能不如其他数据结构高效。

3、计数器类型

对某个key对应的计数器原子的进行加减操作,计数器可以为int, double, uint64_t 等类型,两种不同的计数器类型不能作用于同一个key,由于存储格式不同,计数器的读写需要通过setCount和getCount接口,而不能使用普通的put和get接口。

很简单理解:你int类型的计数器,你put一个 3.5进去,肯定要抛异常。

接口

行为

incr

将某个key的计数器原子加一

decr

将某个key的计数器原子减一

getCount

获取某个计数器当前值

setCount

设置某个计数器的当前值

import com.aliyun.openservices.tair.*;
import com.aliyun.openservices.tair.impl.DefaultTairManager;

public class TairExample {
    public static void main(String[] args) {
        String serverAddress = "xxxxx"; // Tair服务器地址
        String namespace = "your_namespace"; // 命名空间
        int groupId = 0; // Group ID

        // 创建Tair客户端
        TairManager tairManager = new DefaultTairManager(serverAddress, namespace, groupId);

        // 用户ID
        String userId = "user123";

        // 假设点赞一次
        tairManager.incr(userId + "_likes"); // 自增点赞数量

        // 获取点赞数量
        long likesCount = tairManager.getCount(userId + "_likes"); // 获取点赞数量

        // 假设取消点赞一次
        tairManager.decr(userId + "_likes"); // 自减点赞数量

        // 获取点赞数量
        long updatedLikesCount = tairManager.getCount(userId + "_likes"); // 获取更新后的点赞数量

        // 假设记录点赞次数统计
        long totalLikesCount = 1000;
        tairManager.setCount(userId + "_total_likes", totalLikesCount); // 设置点赞次数统计

        // 获取点赞次数统计
        long retrievedTotalLikesCount = tairManager.getCount(userId + "_total_likes"); // 获取点赞次数统计

        // 关闭Tair客户端
        tairManager.close();
    }
}

4、List列表类型

key -> [value1,value2,value3,...]

命令

行为

list_apppend

向list列表后面追加元素

list_get

从某个位置向后取若干元素

list_get_and_remove

同list_get, 取到的元素会进行删除

list_remove

从某个位置向后删除若干个元素

list_removeall

删除整个List的所有元素

import com.alibaba.tair.api.*;
import com.alibaba.tair.api.impl.DefaultTairManager;

import java.util.List;

public class StudentListDemo {

    public static void main(String[] args) {
        // 配置Tair客户端
        TairManager tairManager = new DefaultTairManager();
        tairManager.init(); // 初始化Tair客户端

        // 定义namespace
        String namespace = "student_list_namespace";

        // 模拟学生信息
        String[] studentNames = {"John Doe", "Alice Smith", "Bob Johnson"};

        // 使用 list_append 将多个学生信息添加到列表中
        for (String studentName : studentNames) {
            tairManager.listAppend(namespace, "students", studentName);
        }

        // 使用 list_get 获取列表中的学生信息
        List studentsList = tairManager.listGet(namespace, "students", 0, -1);
        System.out.println("Students List: " + studentsList);

        // 使用 list_get_and_remove 获取列表中的学生信息,并同时从列表中移除
        String removedStudent = tairManager.listGetAndRemove(namespace, "students", 0);
        System.out.println("Removed Student: " + removedStudent);

        // 使用 list_remove 从列表中移除指定学生信息
        tairManager.listRemove(namespace, "students", "Alice Smith");

        // 使用 list_removeall 从列表中移除所有学生信息
        tairManager.listRemoveAll(namespace, "students");

        // 关闭Tair客户端
        tairManager.close();
    }
}

5、Set集合类型

一组无序的元素集合

命令

行为

sadd

添加元素到已知集合

scard

获取一个集合的所有元素

sismember

判断给定元素是否属于此集合

srem

删除集合中的某个元素

srem_all

删除整个集合中的元素

6、Map散列类型

map即就是hash类型的数据结构,是一种key-value形式的字典数据类型,存储了多个键值对之间的映射

命令

行为

map_put

向map写入一组kv

map_get

从指定map中获取若干kv

map_getall

获取map中的全部kv

map_remove

删除指定map中的若干kv

map_removeall

删除map中的所有元素

map_setnx

向指定Map中写入数据。如果写入的子key已存在,则返回失败

map_exist

判断某个子key是否存在给定map中

import com.aliyun.openservices.tair.Client;
import com.aliyun.openservices.tair.Result;
import com.aliyun.openservices.tair.common.ClientConfig;
import com.aliyun.openservices.tair.common.auth.DefaultCredentialProvider;
import com.aliyun.openservices.tair.common.auth.DefaultCredentials;
import com.aliyun.openservices.tair.common.domain.result.FullDataType;
import com.aliyun.openservices.tair.common.domain.result.GetResult;
import com.aliyun.openservices.tair.common.domain.result.MapItem;
import com.aliyun.openservices.tair.ext.impl.DefaultTairManager;
import com.aliyun.openservices.tair.impl.DefaultKVCache;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TairMapExample {
    public static void main(String[] args) {
        // 初始化Tair客户端
        ClientConfig config = new ClientConfig();
        config.setIoThreadNum(2);
        config.setConTimeoutMs(1000);
        config.setRwTimeoutMs(500);
        DefaultTairManager tairManager = new DefaultTairManager();
        tairManager.setConfigServerList("your_config_server_address");
        tairManager.setGroupName("your_group_name");
        tairManager.setNamespace("your_namespace");
        tairManager.init();

        DefaultKVCache cache = (DefaultKVCache) tairManager.getCache("your_cache_name");

        // 向Tair中存储学生信息
        Map studentInfo = new HashMap<>();
        studentInfo.put("name", "Alice");
        studentInfo.put("age", "20");
        studentInfo.put("major", "Computer Science");
        cache.mapPut("student_1", studentInfo);

        // 从Tair中获取学生信息
        GetResult> getResult = cache.mapGet("student_1", FullDataType.VALUE, null);
        Map retrievedStudentInfo = getResult.getValue();
        System.out.println("Retrieved Student Info: " + retrievedStudentInfo);

        // 获取所有学生信息
        List> allStudents = cache.mapGetAll("student_", null, 10, 0);
        System.out.println("All Students: " + allStudents);

        // 从Tair中删除学生信息
        Result removeResult = cache.mapRemove("student_1");
        System.out.println("Remove Result: " + removeResult.getData());

        // 删除所有学生信息
        Result removeAllResult = cache.mapRemoveAll("student_");
        System.out.println("Remove All Result: " + removeAllResult.getData());

        // 设置学生信息,如果key已存在则不更新
        Map newStudentInfo = new HashMap<>();
        newStudentInfo.put("name", "Bob");
        newStudentInfo.put("age", "22");
        newStudentInfo.put("major", "Mathematics");
        Result setNxResult = cache.mapSetnx("student_2", newStudentInfo);
        System.out.println("Setnx Result: " + setNxResult.getData());

        // 判断学生信息是否存在
        Result existResult = cache.mapExist("student_2");
        System.out.println("Exist Result: " + existResult.getData());

        // 关闭Tair客户端
        tairManager.close();
    }
}

7、Hash类型

命令

行为

hset

设置Hash中的字段(键)和对应的值

hget

获取指定字段的值。

hexists 检查指定字段是否存在于Hash中。
hdel 从Hash中删除一个或多个指定字段。
hincrBy 将Hash中指定字段的值递增一个指定的步长。
hkeys 获取Hash中所有字段(键)的名称。
hvals 获取Hash中所有字段的值。
hgetAll 获取Hash中所有字段和对应值的键值对。
import com.aliyun.openservices.tair.Client;
import com.aliyun.openservices.tair.Result;
import com.aliyun.openservices.tair.common.ClientConfig;
import com.aliyun.openservices.tair.common.auth.DefaultCredentialProvider;
import com.aliyun.openservices.tair.common.auth.DefaultCredentials;
import com.aliyun.openservices.tair.common.domain.result.FullDataType;
import com.aliyun.openservices.tair.common.domain.result.GetResult;
import com.aliyun.openservices.tair.common.domain.result.MapItem;
import com.aliyun.openservices.tair.ext.impl.DefaultTairManager;
import com.aliyun.openservices.tair.impl.DefaultKVCache;
import java.util.List;
import java.util.Map;

public class TairHashMethodsExample {
    public static void main(String[] args) {
        // 初始化Tair客户端
        ClientConfig config = new ClientConfig();
        config.setIoThreadNum(2);
        config.setConTimeoutMs(1000);
        config.setRwTimeoutMs(500);
        DefaultTairManager tairManager = new DefaultTairManager();
        tairManager.setConfigServerList("your_config_server_address");
        tairManager.setGroupName("your_group_name");
        tairManager.setNamespace("your_namespace");
        tairManager.init();

        DefaultKVCache cache = (DefaultKVCache) tairManager.getCache("your_cache_name");

        // 使用hget获取学生姓名
        String studentName = cache.hget("student_1", "name");
        System.out.println("Student Name: " + studentName);

        // 使用hset设置学生年龄
        cache.hset("student_1", "age", "20");

        // 使用hexists检查字段是否存在
        boolean exists = cache.hexists("student_1", "age");
        System.out.println("Age exists: " + exists);

        // 使用hdel删除字段
        cache.hdel("student_1", "age");

        // 使用hincrby对数字字段进行增加
        cache.hincrBy("student_1", "score", 10);

        // 使用hkeys获取所有字段名
        List fieldNames = cache.hkeys("student_1");
        System.out.println("Field Names: " + fieldNames);

        // 使用hvals获取所有字段值
        List fieldValues = cache.hvals("student_1");
        System.out.println("Field Values: " + fieldValues);

        // 使用hgetall获取所有字段和值
        Map fieldAndValues = cache.hgetAll("student_1");
        System.out.println("Field and Values: " + fieldAndValues);

        // 关闭Tair客户端
        tairManager.close();
    }
}

8、Map 与 Hash的联系与区别

从功能上来说,Tair 中的 Hash 结构可以用来替代 Map 结构,因为 Hash 结构可以看作是 Map 结构的一种特例。在 Tair 中,Hash 结构和 Map 结构都可以用来存储键值对的数据,但它们有一些区别:

  1. 存储方式:Hash 结构的存储方式更紧凑,适合存储大量的键值对数据,而 Map 结构更具灵活性,适合存储少量的数据项。

  2. 内部实现:Tair 中的 Hash 结构在内部实现上可能会更高效,适合存储大量的键值对。而 Map 结构在存储少量数据时更方便。

  3. 功能扩展:Map 结构的功能更丰富,支持的操作更多,比如 mapGetAll 可以一次性获取所有键值对,而 Hash 结构的类似功能需要使用多个命令来完成。

虽然 Hash 结构可以替代 Map 结构,但在使用时还是要根据具体的业务需求来选择。如果你的数据量较大且需要高效的存储和访问,可以考虑使用 Hash 结构。如果数据量相对较小且需要更灵活的操作,可以选择 Map 结构。同时,考虑到代码的可读性和维护性,也可以根据业务需求选择更符合语义的数据结构。

你可能感兴趣的:(java,前端,服务器)