国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用 TiKV 構建分布式類 Redis 服務

UnixAgain / 2805人閱讀

摘要:提供了集群支持,但也不能支持跨多個節點的分布式事務。是一個高性能,支持分布式事務的數據庫。譬如,我們就構建了,一個基于的,兼容的分布式關系型數據庫。它使用作為每行的分隔符并且用不同的前綴來代表不同的類型。

什么是 Redis

Redis 是一個開源的,高性能的,支持多種數據結構的內存數據庫,已經被廣泛用于數據庫,緩存,消息隊列等領域。它有著豐富的數據結構支持,譬如 String,Hash,Set 和 Sorted Set,用戶通過它們能構建自己的高性能應用。

Redis 非常快,沒準是世界上最快的數據庫了,它雖然使用內存,但也提供了一些持久化機制以及異步復制機制來保證數據的安全。

Redis 的不足

Redis 非常酷,但它也有一些問題:

內存很貴,而且并不是無限容量的,所以我們不可能將大量的數據存放到一臺機器。

異步復制并不能保證 Redis 的數據安全。

Redis 提供了 transaction mode,但其實并不滿足 ACID 特性。

Redis 提供了集群支持,但也不能支持跨多個節點的分布式事務。

所以有時候,我們需要一個更強大的數據庫,雖然在延遲上面可能趕不上 Redis,但也有足夠多的特性,譬如:

豐富的數據結構

高吞吐,能接受的延遲

強數據一致

水平擴展

分布式事務

為什么選擇 TiKV

大約 4 年前,我開始解決上面提到的 Redis 遇到的一些問題。為了讓數據持久化,最直觀的做法就是將數據保存到硬盤上面,而不是在內存里面。所以我開發了 LedisDB,一個使用 Redis 協議,提供豐富數據結構,但將數據放在 RocksDB 的數據庫。LedisDB 并不是完全兼容 Redis,所以后來,我和其他同事繼續創建了 RebornDB,一個完全兼容 Redis 的數據庫。
無論是 LedisDB 還是 RebornDB,因為他們都是將數據放在硬盤,所以能存儲更大量的數據。但它們仍然不能提供 ACID 的支持,另外,雖然我們可以通過 codis 去提供集群的支持,我們也不能很好的支持全局的分布式事務。

所以我們需要另一種方式,幸運的是,我們有 TiKV。

TiKV 是一個高性能,支持分布式事務的 key-value 數據庫。雖然它僅僅提供了簡單的 key-value API,但基于 key-value,我們可以構造自己的邏輯去創建更強大的應用。譬如,我們就構建了 TiDB ,一個基于 TiKV 的,兼容 MySQL 的分布式關系型數據庫。TiDB 通過將 database 的 schema 映射到 key-value 來支持了相關 SQL 特性。所以對于 Redis,我們也可以采用同樣的辦法 - 構建一個支持 Redis 協議的服務,將 Redis 的數據結構映射到 key-value 上面。

如何開始

整個架構非常簡單,我們僅僅需要做的就是構建一個 Redis 的 Proxy,這個 Proxy 會解析 Redis 協議,然后將 Redis 的數據結構映射到 key-value 上面。

Redis Protocol

Redis 協議被叫做 RESP(Redis Serialization Protocol),它是文本類型的,可讀性比較好,并且易于解析。它使用 “rn” 作為每行的分隔符并且用不同的前綴來代表不同的類型。例如,對于簡單的 String,第一個字節是 “+”,所以一個 “OK” 行就是 “+OKrn”。
大多數時候,客戶端會使用最通用的 Request-Response 模型用于跟 Redis 進行交互。客戶端會首先發送一個請求,然后等待 Redis返回結果。請求是一個 Array,Array 里面元素都是 bulk strings,而返回值則可能是任意的 RESP 類型。Redis 同樣支持其他通訊方式:

Pipeline - 這種模式下面客戶端會持續的給 Redis 發送多個請求,然后等待 Redis 返回一個結果。
Push - 客戶端會在 Redis 上面訂閱一個 channel,然后客戶端就會從這個 channel 上面持續受到 Redis push 的數據。

下面是一個簡單的客戶端發送 LLEN mylist 命令到 Redis 的例子:

C: *2

C: $4

C: LLEN

C: $6

C: mylist


S: :48293

客戶端會發送一個帶有兩個 bulk string 的 array,第一個 bulk string 的長度是 4,而第二個則是 6。Redis 會返回一個 48293 整數。正如你所見,RESP 非常簡單,自然而然的,寫一個 RESP 的解析器也是非常容易的。

作者創建了一個 Go 的庫 goredis,基于這個庫,我們能非常容易的從連接上面解析出 RESP,一個簡單的例子:

// Create a buffer IO from the connection.
br := bufio.NewReaderSize(conn, 4096)
// Create a RESP reader.
r := goredis.NewRespReader(br)
// Parse the Request
req := r.ParseRequest()

函數 ParseRequest 返回一個解析好的 request,它是一個 [][]byte 類型,第一個字段是函數名字,譬如 “LLEN”,然后后面的字段則是這個命令的參數。

TiKV 事務 API

在我們開始之前,作者將會給一個簡單實用 TiKV 事務 API 的例子,我們調用 Begin 開始一個事務:

txn, err := db.Begin()

函數 Begin 創建一個事務,如果出錯了,我們需要判斷 err,不過后面作者都會忽略 err 的處理。

當我們開始了一個事務之后,我們就可以干很多操作了:

value, err := txn.Get([]byte(“key”))
// Do something with value and then update the newValue to the key.
txn.Put([]byte(“key”), newValue)

上面我們得到了一個 key 的值,并且將其更新為新的值。TiKV 使用樂觀事務模型,它會將所有的改動都先緩存到本地,然后在一起提交給 Server。

// Commit the transaction
txn.Commit(context.TODO())

跟其他事務處理一樣,我們也可以回滾這個事務:

txn.Rollback()

如果兩個事務操作了相同的 key,它們就會沖突。一個事務會提交成功,而另一個事務會出錯并且回滾。

映射 Data structure 到 TiKV

現在我們知道了如何解析 Redis 協議,如何在一個事務里面做操作,下一步就是支持 Redis 的數據結構了。Redis 主要有 4 中數據結構:String,Hash,Set 和 Sorted Set,但是對于 TiKV 來說,它只支持 key-value,所以我們需要將這些數據結構映射到 key-value。

首先,我們需要區分不同的數據結構,一個非常容易的方式就是在 key 的后面加上 Type flag。例如,我們可以將 ’s’ 添加到 String,所以一個 String key “abc” 在 TiKV 里面其實就是 “abcs”。

對于其他類型,我們可能需要考慮更多,譬如對于 Hash 類型,我們需要支持如下操作:

HSET key field1 value1
HSET key field2 value2
HLEN key

一個 Hash 會有很多 fields,我有時候想知道整個 Hash 的個數,所以對于 TiKV,我們不光需要將 Hash 的 key 和 field 合在一起變成 TiKV 的一個 key,也同時需要用另一個 key 來保存整個 Hash 的長度,所以整個 Hash 的布局類似:

key + ‘h’ -> length
key + ‘f’ + field1 -> value
key + ‘f’ + field2 -> value 

如果我們不保存 length,那么如果我們想知道 Hash 的 length,每次都需要去掃整個 Hash 得到所有的 fields,這個其實并不高效。但如果我們用另一個 key 來保存 length,任何時候,當我們加入一個新的 field,我們都需要去更新這個 length 的值,這也是一個開銷。對于我來說,我傾向于使用另一個 key 來保存 length,因為 HLEN 是一個高頻的操作。

例子

作者構建了一個非常簡單的例子 example ,里面只支持 String 和 Hash 的一些操作,我們可以 clone 下來并編譯:

git clone https://github.com/siddontang/redis-tikv-example.git $GOPATH/src/github.com/siddontang/redis-tikv-example

cd $GOPATH/src/github.com/siddontang/redis-tikv-example
go build

在運行之前,我們需要啟動 TiKV,可以參考 instruction,然后執行:

./redis-tikv-example

這個例子會監聽端口 6380,然后我們可以用任意的 Redis 客戶端,譬如 redis-cli 去連接:

redis-cli -p 6380
127.0.0.1:6380> set k1 a
OK
127.0.0.1:6380> get k1
"a"
127.0.0.1:6380> hset k2 f1 a
(integer) 1
127.0.0.1:6380> hget k2 f1
"a"
尾聲

現在已經有一些公司基于 TiKV 來構建了他們自己的 Redis Server,并且也有一個開源的項目 tidis 做了相同的事情。tidis 已經比較完善,如果你想替換自己的 Redis,可以嘗試一下。

正如同你所見,TiKV 其實算是一個基礎的組件,我們可以在它的上面構建很多其他的應用。如果你對我們現在做的事情感興趣,歡迎聯系我:tl@pingcap.com。

作者:唐劉
原文鏈接:https://www.jianshu.com/p/b4dee8372d8d

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17787.html

相關文章

發表評論

0條評論

UnixAgain

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<