1. 程式人生 > >redis數據類型

redis數據類型

script 超過 depend 發送消息 鍵值 發布者 keys 創建 dir

Redis - 數據類型

Redis支持5種類型的數據類型,它描述如下的:

字符串

Redis字符串是字節序列。Redis字符串是二進制安全的,這意味著他們有一個已知的長度沒有任何特殊字符終止,所以你可以存儲任何東西,512兆為上限。

例子

redis 127.0.0.1:6379> SET name "yiibai"
OK
redis 127.0.0.1:6379> GET name
"yiibai"

上面是Redis的set和get命令的例子,Redis名稱為yiibai使用的key存儲在Redis的字符串值。

哈希

Redis的哈希是鍵值對的集合。 Redis的哈希值是字符串字段和字符串值之間的映射,因此它們被用來表示對象

例子

redis 127.0.0.1:6379> HMSET user:1 username yiibai password yiibai points 200
OK
redis 127.0.0.1:6379> HGETALL user:1

1) "username"
2) "yiibai"
3) "password"
4) "yiibai"
5) "points"
6) "200"

在上面的例子中的哈希數據類型,用於存儲其中包含的用戶的基本信息用戶的對象。這裏HMSET,HEGTALL用戶命令user:1是鍵。

列表

Redis的列表是簡單的字符串列表,排序插入順序。您可以添加元素到Redis的列表的頭部或尾部。

例子

redis 127.0.0.1:6379> lpush tutoriallist redis
(integer) 1
redis 127.0.0.1:6379> lpush tutoriallist mongodb
(integer) 2
redis 127.0.0.1:6379> lpush tutoriallist rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange tutoriallist 0 10

1) "rabitmq"
2) "mongodb"
3) "redis"

列表的最大長度為 232

- 1 元素(4294967295,每個列表中可容納超過4十億的元素)。

集合

Redis的集合是字符串的無序集合。在Redis您可以添加,刪除和測試文件是否存在,在成員O(1)的時間復雜度。

例子

redis 127.0.0.1:6379> sadd tutoriallist redis
(integer) 1
redis 127.0.0.1:6379> sadd tutoriallist mongodb
(integer) 1
redis 127.0.0.1:6379> sadd tutoriallist rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd tutoriallist rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers tutoriallist

1) "rabitmq"
2) "mongodb"
3) "redis"

註意:在上面的例子中rabitmq集合添加加兩次,但由於集合元素具有唯一屬性。

集合中的元素最大數量為 232 - 1 (4294967295,可容納超過4十億元素)。

有序集合

Redis的有序集合類似於Redis的集合,字符串不重復的集合。不同的是,一個有序集合的每個成員用分數,以便采取有序set命令,從最小的到最大的成員分數有關。雖然成員具有唯一性,但分數可能會重復。

例子

redis 127.0.0.1:6379> zadd tutoriallist 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd tutoriallist 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd tutoriallist 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd tutoriallist 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE tutoriallist 0 1000

1) "redis"
2) "mongodb"
3) "rabitmq"

Redis - keys

Redis keys命令用於在Redis的管理鍵。Redis keys命令使用語法如下所示:

語法

redis 127.0.0.1:6379> COMMAND KEY_NAME

例子

redis 127.0.0.1:6379> SET yiibai redis
OK
redis 127.0.0.1:6379> DEL yiibai
(integer) 1

在上面的例子中DEL是命令,而yiibai是key。如果key被刪除,那麽輸出該命令將是(整數)1,否則它會是(整數)0

Redis - Strings

Redis strings命令用於在Redis的管理字符串值。Redis strings命令的使用語法,如下所示:

語法

redis 127.0.0.1:6379> COMMAND KEY_NAME

例子

redis 127.0.0.1:6379> SET yiibai redis
OK
redis 127.0.0.1:6379> GET yiibai
"redis"

在上面的例子SET和GET是命令,而yiibai是key。

Redis - 哈希

Redis的哈希值是字符串字段和字符串值之間的映射,所以他們是代表對象的完美數據類型

在Redis的哈希值,最多可存儲超過400十億字段 - 值對。

例子

redis 127.0.0.1:6379> HMSET yiibai name "redis tutorial" description "redis basic commands for caching" likes 20 visitors 23000
OK
redis 127.0.0.1:6379> HGETALL yiibai

1) "name"
2) "redis tutorial"
3) "description"
4) "redis basic commands for caching"
5) "likes"
6) "20"
7) "visitors"
8) "23000"

在上面的例子中,已經在哈希命名yiibai的Redis集合名為tutorials(name, description, likes, visitors)

Redis - 列表

Redis的列表是簡單的字符串列表,排序插入順序。您可以添加Redis元素在列表頭部或列表的尾部。

列表的最大長度為 232 - 1 個元素(每個列表元素個數超過4294967295)。

例子

redis 127.0.0.1:6379> LPUSH tutorials redis
(integer) 1
redis 127.0.0.1:6379> LPUSH tutorials mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH tutorials mysql
(integer) 3
redis 127.0.0.1:6379> LRANGE tutorials 0 10

1) "mysql"
2) "mongodb"
3) "redis"

在上述例子中的三個值被插入在redis列表名為LPUSH的命令教程。

Redis - 集合

Redis的集合是唯一的字符串的無序集合。集合的唯一性不允許數據的重復的鍵。

在Redis的集合添加,刪除和測試文件是否存在成員在O(1)(常數時間不管裏面包含的元素集合的數量)。集合的最大長度為 232 - 1 個元素(每集合超過4294967295元素)。

例子

redis 127.0.0.1:6379> SADD tutorials redis
(integer) 1
redis 127.0.0.1:6379> SADD tutorials mongodb
(integer) 1
redis 127.0.0.1:6379> SADD tutorials mysql
(integer) 1
redis 127.0.0.1:6379> SADD tutorials mysql
(integer) 0
redis 127.0.0.1:6379> SMEMBERS tutorials

1) "mysql"
2) "mongodb"
3) "redis"

在上述例子中的三個值被命令SADD插入redis的集合名稱tutorials。

Redis有序集

Redis的有序集合類似Redis的集合存儲在設定值具有唯一性。不同的是,一個有序集合的每個成員用分數,以便采取有序set命令,從最小的到最大的分數有關。

在Redis的有序set添加,刪除和測試存在成員O(1)(固定時間,無論裏面包含集合元素的數量)。列表的最大長度為 232 - 1 個元素(每集合超過4294967295元素)。

例子

redis 127.0.0.1:6379> ZADD tutorials 1 redis
(integer) 1
redis 127.0.0.1:6379> ZADD tutorials 2 mongodb
(integer) 1
redis 127.0.0.1:6379> ZADD tutorials 3 mysql
(integer) 1
redis 127.0.0.1:6379> ZADD tutorials 3 mysql
(integer) 0
redis 127.0.0.1:6379> ZADD tutorials 4 mysql
(integer) 0
redis 127.0.0.1:6379> ZRANGE tutorials 0 10 WITHSCORES

1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

在上述例子中的三個值被命令ZADD插入其得分在redis的有序集命名為tutorials。

Redis - HyperLogLog

Redis的HyperLogLog使用隨機化,以提供唯一的元素數目近似的集合只使用一個常數,並且體積小,少量內存的算法。

HyperLogLog提供,即使每個使用了非常少量的內存(12千字節),標準誤差為集合的基數非常近似,沒有限制的條目數,可以指定,除非接近 264個條目。

例子

下面的示例說明Redis的HyperLogLog工作原理:

redis 127.0.0.1:6379> PFADD tutorials "redis"

1) (integer) 1

redis 127.0.0.1:6379> PFADD tutorials "mongodb"

1) (integer) 1

redis 127.0.0.1:6379> PFADD tutorials "mysql"

1) (integer) 1

redis 127.0.0.1:6379> PFCOUNT tutorials

(integer) 3

Redis - 訂閱

Redis的訂閱實現了郵件系統,發送者(在Redis的術語中被稱為發布者)發送的郵件,而接收器(用戶)接收它們。由該消息傳送的鏈路被稱為通道。

在Redis客戶端可以訂閱任何數目的通道。

示例

以下舉例說明如何發布用戶的概念工作。在下面的例子給出一個客戶端訂閱一個通道名為redisChat

redis 127.0.0.1:6379> SUBSCRIBE redisChat

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

現在,兩個客戶端都發布在同一個命名通道redisChat消息,並且以上訂閱客戶端接收消息。

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"

(integer) 1

redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by tutorials point"

(integer) 1


1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "Learn redis by tutorials point"

Redis - 事務

Redis事務讓一組命令在單個步驟執行。事務中有兩個屬性,說明如下:

  • 在一個事務中的所有命令按順序執行作為單個隔離操作。通過另一個客戶端發出的請求在Redis的事務的過程中執行,這是不可能的。

  • Redis的事務具有原子性。原子意味著要麽所有的命令都執行或都不執行。

例子

Redis的事務由指令多重發起,然後需要傳遞在事務,而且整個事務是通過執行命令EXEC執行命令列表。

redis 127.0.0.1:6379> MULTI
OK
List of commands here
redis 127.0.0.1:6379> EXEC

例子

以下舉例說明Redis事務如何啟動並執行。

redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> SET tutorial redis
QUEUED
redis 127.0.0.1:6379> GET tutorial
QUEUED
redis 127.0.0.1:6379> INCR visitors
QUEUED
redis 127.0.0.1:6379> EXEC

1) OK
2) "redis"
3) (integer) 1

Redis - 腳本

Redis腳本使用Lua解釋腳本用於評估計算。它內置的Redis,從2.6.0版本開始使用腳本命令 eval。

語法

eval命令的基本語法如下:

redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]

例子

以下舉例說明Redis腳本的工作原理:

redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

1) "key1"
2) "key2"
3) "first"
4) "second"

Redis - 連接

Redis的連接命令基本上都是用於管理與Redis的服務器客戶端連接。

Example

下面的例子說明了一個客戶如何通過Redis服務器驗證自己,並檢查服務器是否正在運行。

redis 127.0.0.1:6379> AUTH "password"
OK
redis 127.0.0.1:6379> PING
PONG

Redis - 備份

Redis SAVE命令用來創建當前的 Redis 數據庫備份。

語法

對Redis SAVE命令的基本語法如下所示:

127.0.0.1:6379> SAVE

例子

下面的示例顯示了 Redis 當前數據庫如何創建備份。

127.0.0.1:6379> SAVE

OK

這個命令將創建dump.rdb文件在Redis目錄中。

還原Redis數據

要恢復Redis的數據只需移動 Redis 的備份文件(dump.rdb)到 Redis 目錄,然後啟動服務器。為了得到你的 Redis 目錄,使用配置命令如下所示:

127.0.0.1:6379> CONFIG get dir

1) "dir"
2) "/user/yiibai/redis-2.8.13/src"

在上述命令的輸出在 /user/yiibai/redis-2.8.13/src 目錄,在安裝redis的服務器安裝位置。

Bgsave

要創建Redis的備份備用命令BGSAVE也可以。這個命令將開始執行備份過程,並在後臺運行。

例子

127.0.0.1:6379> BGSAVE

Background saving started

Redis - 安全

可以Redis的數據庫更安全,所以相關的任何客戶端都需要在執行命令之前進行身份驗證。客戶端輸入密碼匹配需要使用Redis設置在配置文件中的密碼。

例子

下面給出的例子顯示的步驟,以確保您的Redis實例安全。

127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) ""

默認情況下,此屬性為空,表示沒有設置密碼,此實例。您可以通過執行以下命令來更改這個屬性

127.0.0.1:6379> CONFIG set requirepass "yiibai"
OK
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "yiibai"

設置密碼,如果客戶端運行命令沒有驗證,會提示(錯誤)NOAUTH,需要通過驗證。錯誤將返回客戶端。因此,客戶端需要使用AUTHcommand進行認證。

語法

AUTH命令的基本語法如下所示:

127.0.0.1:6379> AUTH password

Redis - 基準

Redis基準是公用工具同時運行Ñ命令檢查Redis的性能。

語法

redis的基準的基本語法如下所示:

redis-benchmark [option] [option value]

例子

下面給出的例子檢查redis調用100000命令。

redis-benchmark -n 100000

PING_INLINE: 141043.72 requests per second
PING_BULK: 142857.14 requests per second
SET: 141442.72 requests per second
GET: 145348.83 requests per second
INCR: 137362.64 requests per second
LPUSH: 145348.83 requests per second
LPOP: 146198.83 requests per second
SADD: 146198.83 requests per second
SPOP: 149253.73 requests per second
LPUSH (needed to benchmark LRANGE): 148588.42 requests per second
LRANGE_100 (first 100 elements): 58411.21 requests per second
LRANGE_300 (first 300 elements): 21195.42 requests per second
LRANGE_500 (first 450 elements): 14539.11 requests per second
LRANGE_600 (first 600 elements): 10504.20 requests per second
MSET (10 keys): 93283.58 requests per second

Redis - 客戶端連接

Redis接受配置監聽TCP端口和Unix套接字客戶端的連接,如果啟用。當一個新的客戶端連接被接受以下操作進行:

  • 客戶端套接字置於非阻塞狀態,因為Redis使用復用和非阻塞I/O操作。

  • TCP_NODELAY選項設定是為了確保我們沒有在連接時延遲。

  • 創建一個可讀的文件時,這樣Redis能夠盡快收集客戶端的查詢作為新的數據可供讀取的套接字。

客戶端的最大數量

在Redis的配置(redis.conf)屬性調用maxclients,它描述客戶端可以連接到Redis的最大數量。命令的基本語法是:

config get maxclients

1) "maxclients"
2) "10000"

默認情況下,此屬性設置為10000(這取決於操作系統的文件描述符限制最大數量),但你可以改變這個屬性。

例子

在下面給出的例子中,在啟動服務器我們設置客戶端的最大數量為10萬。

redis-server --maxclients 100000

Redis - 管道傳輸

Redis是一個TCP服務器,並支持請求/響應協議。在redis一個請求完成下面的步驟:

  • 客戶端發送一個查詢到服務器,並從套接字中讀取,通常在阻塞的方式,對服務器的響應。

  • 服務器處理命令並將響應返回給客戶端。

管道傳輸的含義

管道的基本含義是,客戶端可以發送多個請求給服務器,而無需等待答復所有,並最後讀取在單個步驟中的答復。

例子

要檢查redis的管道,只要啟動Redis實例,然後在終端鍵入以下命令。

$(echo -en "PING\r\n SET tutorial redis\r\nGET tutorial\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379

+PONG
+OK
redis
:1
:2
:3

在上述例子中,我們必須使用PING命令檢查Redis的連接,之後,我們已經設定值的Redis字符串命名tutorial ,之後拿到key的值和增量訪問量的三倍。在結果中,我們可以檢查所有的命令都一次提交給Redis,Redis是在一個步驟給出所有命令的輸出。

管道的好處

這種技術的好處是極大地改善協議的性能。通過管道將慢互聯網連接速度從5倍的連接速度提高到localhost至少達到百過倍。

Redis - 分區

分區是一種將數據分成多個Redis的情況下,讓每一個實例將只包含你的鍵字的子集的過程。

分區的好處

  • 它允許更大的數據庫,使用的多臺計算機的存儲器的總和。如果不分區,一臺計算機的內存可支數量有限。

  • 它允許以大規模的計算能力,以多個內核和多個計算機,以及網絡帶寬向多臺計算機和網絡適配器。

分區的缺點

  • 通常不支持涉及多個鍵的操作。例如,不能兩個集合之間執行交叉點,因為它們存儲在被映射到不同Redis實例中的鍵。

  • 涉及多個鍵的Redis事務不能被使用。

  • 分區粒度是關鍵,所以它是不可能分片數據集用一個碩大的鍵是一個非常大的有序集合。

  • 當分區時,數據處理比較復雜,比如要處理多個RDB/AOF文件,使數據備份需要從多個實例和主機聚集持久性文件。

  • 添加和刪除的能力可能很復雜。比如Redis的集群支持有添加,並在運行時刪除節點不支持此功能的能力,但其他系統,如客戶端的分區和代理的數據大多是透明的重新平衡。但是有一個叫Presharding技術有助於在這方面。

分區的類型

redis的提供有兩種類型的分區。假設我們有四個Redis實例R0,R1,R2,R3和代表用戶很多鍵如:user:1, user:2, ... 等等

範圍分區

範圍分區被映射對象轉化為具體的Redis實例的範圍內實現。假定在本例中用戶ID0?ID10000將進入實例R0,而用戶形成ID10001至20000號將進入實例R1等等。

散列分區

在這種類型的分區,一個散列函數(例如,模數函數)被用於轉換鍵成數字,然後數據被存儲在不同redis的實例。

==============================================================================================================

與Spring集成

我需要哪些jar包?

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

如何配置spring配置文件?

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--配置IP地址與端口號,連接redis服務器-->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:hostName="127.0.0.1" p:port="6379" p:usePool="true"/>
    <!--配置redisTemplate-->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="jedisConnectionFactory"/>
    <!--配置stringRedisTemplate-->
    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connectionFactory-ref="jedisConnectionFactory"/>
</beans>

一般情況,只需要配置RedisTemplate或StringRedisTemplate其中一個就行,常用的為StringRedisTemplate。

RedisTemplate與StringRedisTemplate的區別?

StringRedisTemplate:

public class StringRedisTemplate extends RedisTemplate<String, String> {
    public StringRedisTemplate() {
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        this.setKeySerializer(stringSerializer);
        this.setValueSerializer(stringSerializer);
        this.setHashKeySerializer(stringSerializer);
        this.setHashValueSerializer(stringSerializer);
    }

    public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
        this();
        this.setConnectionFactory(connectionFactory);
        this.afterPropertiesSet();
    }

    protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
        return new DefaultStringRedisConnection(connection);
    }
}

從上面的代碼可以看出,StringRedisTemplate繼承了鍵值類型都為String的RedisTemplate,且使用StringRedisSerializer作為序列化工具。所以StringRedisTemplate能使用的方法,RedisTemplate都能使用,下面的例子只會展示StringRedisTemplate的方法。

StringRedisSerializer:

public class StringRedisSerializer implements RedisSerializer<String> {
    private final Charset charset;

    public StringRedisSerializer() {
        this(Charset.forName("UTF8"));
    }

    public StringRedisSerializer(Charset charset) {
        Assert.notNull(charset);
        this.charset = charset;
    }

    public String deserialize(byte[] bytes) {
        return bytes == null?null:new String(bytes, this.charset);
    }

    public byte[] serialize(String string) {
        return string == null?null:string.getBytes(this.charset);
    }
}

可以看出,StringRedisSerializer使用UTF8字符集處理字符串。

使用API操作基本redis基本數據類型


spring提供哪些接口操作redis基本數據?

第一組

ValueOperations:字符串類型操作
ListOperations:列表類型操作
SetOperations:集合類型操作
ZSetOperations:有序集合類型操作
HashOperations:散列操作

第二組

BoundValueOperations:字符串類型操作
BoundListOperations:列表類型操作
BoundSetOperations:集合類型操作
BoundZSetOperations:有序集合類型操作
BoundHashOperations:散列操作

如何獲得接口的實現?

第一組

ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
SetOperations<String, String> setOperations = stringRedisTemplate.opsForSet();
ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();

第二組

BoundValueOperations<String, String> valueOperations = stringRedisTemplate.boundValueOps("key");
BoundListOperations<String, String> listOperations = stringRedisTemplate.boundListOps("key");
BoundSetOperations<String, String> setOperations = stringRedisTemplate.boundSetOps("key");
BoundZSetOperations<String, String> zSetOperations = stringRedisTemplate.boundZSetOps("key");
BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.boundHashOps("key");

從上面兩組實現可以發現,第二組API只是在第一組API的上面將key值的綁定放在獲得接口時了,此舉方便了每次操作基本數據類型的時候不用反復的去填寫key值,只需要操作具體的value就行了。

具體有哪些數據操作方式,如ValueOperations的get與set,ListOperations的push與pop等可以參照:Redis學習筆記(2)-Redis數據類型。他們的方法簽名與客戶端redis-cli操作redis時的簽名是一樣的。

使用API操作消息隊列


使用API前需要了解

Redis學習筆記(3)-Redis事務,過期時間,隊列

如何發送消息隊列?

RedisTemplate template = template.convertAndSend("channel", "message");

第一個參數為發送的消息的頻道,第二個參數為消息本身。

如何接受隊列中的消息?

public interface MessageDelegate {
  void handleMessage(String message);
  void handleMessage(Map message); void handleMessage(byte[] message);
  void handleMessage(Serializable message);
  void handleMessage(Serializable message, String channel);
}

首先,需要一個符合MessageDelegate 接口方法簽名的類,這個類是自定義的,可以使用MessageDelegate 中的一個或多個簽名方式,如:

public class UserMessageDelegate {
    public void handleMessage(String message) {
        System.out.println(message);
    }
}

得到此類後,將此類註冊到消息監聽容器中:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:redis="http://www.springframework.org/schema/redis"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/redis
       http://www.springframework.org/schema/redis/spring-redis.xsd">

    <redis:listener-container>
        <redis:listener ref="listener" method="handleMessage" topic="chatroom"/>
    </redis:listener-container>

    <bean id="listener" class="com.hzw.redis.listener.UserMessageDelegate"/>

</beans>

其中,topic就是你要監聽的頻道。

http://blog.csdn.net/qq_29994609/article/details/51772394

redis數據類型