什么是 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\r\n

  C:$4\r\n

  C:LLEN\r\n

  C:$6\r\n

  C:mylist\r\n

  S::48293\r\n

  客户端会发送一个带有两个 bulk string 的 array,第一个 bulk string 的长度是 4,而第二个则是 6。Redis 会返回一个 48293 整数。正如你所见,RESP 非常简单,自然而然的,写一个 RESP 的解析器也是非常容易的。

  作者创建了一个 Go 的库goredis,基于这个库,我们能非常容易的从连接上面解析出 RESP,一个简单的例子:

  //CreateabufferIOfromtheconnection.br:=bufio.NewReaderSize(conn,4096)//CreateaRESPreader.r:=goredis.NewRespReader(br)//ParsetheRequestreq:=r.ParseRequest()

  函数ParseRequest返回一个解析好的 request,它是一个[][]byte类型,第一个字段是函数名字,譬如 “LLEN”,然后后面的字段则是这个命令的参数。

  TiKV 事务 API

  在我们开始之前,作者将会给一个简单实用 TiKV 事务 API 的例子,我们调用Begin开始一个事务:

  txn,err:=db.Begin()

  函数Begin创建一个事务,如果出错了,我们需要判断 err,不过后面作者都会忽略 err 的处理。

  当我们开始了一个事务之后,我们就可以干很多操作了:

  value,err:=txn.Get([]byte(“key”))//DosomethingwithvalueandthenupdatethenewValuetothekey.txn.Put([]byte(“key”),newValue)

  上面我们得到了一个 key 的值,并且将其更新为新的值。TiKV 使用乐观事务模型,它会将所有的改动都先缓存到本地,然后在一起提交给 Server。

  //Committhetransactiontxn.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 类型,我们需要支持如下操作:

  HSETkeyfield1value1

  HSETkeyfield2value2

  HLENkey

  一个 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 下来并编译:

  gitclonehttps://github.com/siddontang/redis-tikv-example.git$GOPATH/src/github.com/siddontang/redis-tikv-examplecd$GOPATH/src/github.com/siddontang/redis-tikv-example

  gobuild

  在运行之前,我们需要启动 TiKV,可以参考instruction,然后执行:

  ./redis-tikv-example

  这个例子会监听端口 6380,然后我们可以用任意的 Redis 客户端,譬如redis-cli去连接:

  redis-cli-p6380

  127.0.0.1:6380setk1a

  OK

  127.0.0.1:6380getk1a127.0.0.1:6380hsetk2f1a

  (integer)1

  127.0.0.1:6380hgetk2f1a

  尾声

  现在已经有一些公司基于 TiKV 来构建了他们自己的 Redis Server,并且也有一个开源的项目tidis做了相同的事情。tidis已经比较完善,如果你想替换自己的 Redis,可以尝试一下。

  正如同你所见,TiKV 其实算是一个基础的组件,我们可以在它的上面构建很多其他的应用。

转载于:https://juejin.im/post/5c00f3ef51882526f96b47bc

使用 TiKV 构建分布式类 Redis 服务相关推荐

  1. 分布式缓存Redis应用场景解析

    Redis的应用场景非常广泛.虽然Redis是一个key-value的内存数据库,但在实际场景中,Redis经常被作为缓存来使用,如面对数据高并发的读写.海量数据的读写等. 举个例子,A网站首页一天有 ...

  2. 浅析redis与zookeeper构建分布式锁的异同

    作者:架构小菜 链接:https://www.jianshu.com/p/508620a76e00 进程请求分布式锁时一般包含三个阶段:1. 进程请求获取锁:2. 获取到锁的进程持有锁并执行业务逻辑: ...

  3. 《Redis官方文档》用Redis构建分布式锁

    <Redis官方文档>用Redis构建分布式锁 用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现 ...

  4. 《Redis官方文档》用Redis构建分布式锁(悲观锁)

    2019独角兽企业重金招聘Python工程师标准>>> **用Redis构建分布式锁 ** 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章 ...

  5. 使用Redis实现高并发分布式序列号生成服务

    序列号的构成 为建立良好的数据治理方案,作数据掌握.分析.统计.商业智能等用途,业务数据的编码制定通常都会遵循一定的规则,一般来讲,都会有自己的编码规则和自增序列构成.比如我们常见的身份证号.银行卡号 ...

  6. Spring Cloud构建分布式电子商务平台:服务消费(基础)

    使用LoadBalancerClient 在Spring Cloud Commons中提供了大量的与服务治理相关的抽象接口,包括DiscoveryClient.这里我们即将介绍的LoadBalance ...

  7. Codis——分布式Redis服务的解决方案

    Codis--分布式Redis服务的解决方案 参考文章: (1)Codis--分布式Redis服务的解决方案 (2)https://www.cnblogs.com/chenny7/p/5063368. ...

  8. Redis构建分布式锁——Redlock

    本文来自:http://ifeve.com/redis-lock/ 简介 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁 ...

  9. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloopimport tornado.webfrom myhash ...

最新文章

  1. Go 中 time.Parse 报错:year/month/day hour/minute/second out of range 时间格式化为什么是 2006-01-02 15:04:05?
  2. 使用Python,OpenCV进行Tesseract-OCR绑定及识别
  3. 谈谈中台架构之交易中台
  4. VHD安装的Win7 X64系统迁移到VMware虚拟机(P2V)...
  5. poj 1118 Lining Up(水题)
  6. Spring Cloud异常
  7. jMatter:提高开发速度10倍!
  8. 【CodeVS - 3639】(树的重心模板,裸题)
  9. OpenGL 视图和颜色的概念
  10. Python-Flask实现基金自选网站
  11. python从某个字符串开始截取_Python字符串的截取
  12. 苹果,你拿什么勇气来跟 Android 比?
  13. 【推荐】HTML5 Word Cloud——中文词云
  14. 主键重复和唯一索引冲突_深入了解数据库索引
  15. HDU 5348 MZL's endless loop(DFS去奇数度点+欧拉回路)
  16. Android替换开机动画
  17. phpdesigner8 php7.0,让getter和setter在phpDesigner8中运行
  18. 周杰伦新歌刷爆朋友圈的背后 付费音乐的春天终于来了?
  19. 人脸识别最全知识图谱,中国学者数量全球第三—清华大学出品
  20. 阿里巴巴高级技术专家:如何成为优秀的技术主管(上篇)

热门文章

  1. 自己的电脑上怎么用python-如何做一个任何电脑都能用的python程序?
  2. python编程实例视屏-python实现实时视频流播放代码实例
  3. python软件代码示例-用Python写一个模拟qq聊天小程序的代码实例
  4. python在当前目录创建txt文件-python-在目录中创建多个文本文件的字数字...
  5. pyhon滤镜详细教程
  6. 华为鸿蒙系统新机发布时间,华为鸿蒙OS发布会定档,或将有多款新机亮相
  7. zend studio输出中文乱码的问题
  8. TortoiseSVN客户端重新设置用户名和密码
  9. T2821 天使之城 codevs
  10. 05章项目:我的租房网