分布式存储kv

KV 数据库

KV,Key-Value,让人想定Mongo数据库,和JSON数据交换格式。 数据存储,存储的数据主要分两种:结构数据(关系表),非结构数据(大文件,杂数据(模式和内容揉合(HTML))

分布式存储系统

1、分布式文件系统:存储文本,图片,音视频等非结构化数据。如google的GFS/colossus和开源的hdfs。

2、分布式键值系统:存储简单的半结构化数据。NoSql的分布式扩展,只提供基于key的增删改查(CRUD)功能。如Amazon的Dynamo。

3、分布式表格系统:存储复杂的半结构化数据。相较于分布式kv系统,他还支持基于key的范围查找。但相对于关系型数据库,他不支持复杂的操作,如多表关联,嵌套查询。典型的系统如google的bigtable和开源的hbase。

4、分布式数据库:存储结构化数据。分布式的关系型数据库。提供SQL关系查询语言。如:google的spanner和开源的hive。

单机存储引擎

存储系统提供的基本功能包括:增删改查(CRUD==增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete))。不同的存储方案根据业务不同侧重点不同,导致存储系统的性能和功能具有一定的差异。

目前主要的单机存储引擎有:

1、哈希存储:hash的CRUD是最快的。但缺点是不支持顺序扫描。bitcask是一个基于hash表结构的存储系统。他将写操作(包括删除标识)追加到文件尾。并定期合并新老文件&记录。

2、B树:既支持随机读取又支持范围查找的系统。查找时间复杂度为logd(n)(d为每个节点的出度)。Mysql的InnoDB的引擎和OS的文件系统使用的就是B+树。(为什么选择使用B树的变种B+树,读者有兴趣可以去探究下。提示:磁盘读取)

3、LSM树(Log Structured Merge Tree):由B+数改进而来。其思想为:将增量写操作保存在内存中,超过阈值时刷入磁盘,从而减少随机写磁盘操作。读操作则需要合并磁盘数据和内存中的写操作。通过Memtable/SSTable实现,实现细节在此不做深入探究。比较适合写操作较多的业务场景。BigTable/HBase/Cassandra中的列簇的数据存储方式采用的即是LSM树。

RocksDB

RocksDB相对传统的关系数据库的一大改进是采用LSM树存储引擎。LSM树是非常有创意的一种数据结构,它和传统的B+树不太一样.

RocksDB的主要设计目标是保证存取快速存储器和高负载服务器更高效,保证充分利用Flash或RAM子系统提供的高速率读写,支持高效的查找和范围scan,支持高负载的随机读、高负载的更新操作或两者的结合。其架构应该支持高并发读写和容量大增时系统的一致性。

RocksDB是一个嵌入式键值存储器,其中键和值是任意的字节流。RocksDB中的所有数据是按序存放的。常见操作包括Get(key), Put(key), Delete(key) and Scan(key)。 RocksDB有三个基本结构:RocksDB memtable,sstfile和logfile。memtable是一个内存数据结构——新数据会插入到memtable和日志文件(可选)。日志文件是 顺序写入的,位于磁盘。当memtable写满后,数据会被刷新到磁盘上的sstfile文件,同时相应的日志文件可以安全地删除。sstfile中的数据经过排序的,目的 是为了加快键查找。

redis

REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。 Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

Redis 优势

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

String(字符串):

string 是 redis 最基本的类型,是二进制安全的,可以包含任何数据。比如jpg图片或者序列化的对象。string 类型的值最大能存储 512MB。

Hash(哈希):

Redis hash 是一个键值(key=>value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

> HSET user:1000 email "john.smith@example.com"
(integer) 1
> HSET user:1000 name "John Smith"
(integer) 1

> hgetall user:1000
1) "email"
2) "john.smith@example.com"
3) "name"
4) "John Smith"

列表数据:

列表是一系列有序值。一些与列表交互的重要的命令是RPUSH,LPUSH,LLEN,LRANGE,LPOP和RPOP。

RPUSH将新元素放在列表的末尾,LPUSH将新元素放在列表的开头。

LRANGE检索列表的子集。它以要检索的第一个元素的索引为第一个参数,以要检索的最后一个元素的索引为第二个参数。第二个参数的值-1表示检索元素直到列表的末尾,-2表示包括最多倒数第二个。

LPOP从列表中删除第一个元素并返回它,RPOP从列表中删除最后一个元素并返回它。 LLEN获取列表的当前长度。

集合数据SET:

string 类型的无序集合。

使用集合时,一些重要的命令是SADD,SREM,SISMEMBER,SMEMBERS和SUNION。

SADD将给定的成员添加到集合中,该命令也是可变的。SREM从集合中删除给定的成员,返回1或0表示该成员是否确实存在。

SISMEMBER测试给定值是否在集合中。如果该值存在,则返回1,否则返回0。

SMEMBERS返回此集合的所有成员的列表。

SUNION组合两个或更多集合,并返回所有元素的列表。

zset(sorted set:有序集合):

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:

redis> SELECT 1
OK
redis [1] > GET foo
(nil)

首先Redis不支持自定义数据库的名字

Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问

最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据

综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内在只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。

中文乱码

要在 redis-cli 后面加上 –raw

redis-cli --raw

就可以避免中文乱码了。

Redis HyperLogLog

每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。

Redis 发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。

Redis 安全

我们可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全。

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

Redis 管道技术

Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。

参考:

  1. 分布式系统之数据存储&分布概览
  2. 一张图看懂小米开源的分布式KV存储系统Pegasus
  3. RocksDB简介
  4. Memcached与Redis有什么区别
  5. https://www.runoob.com/redis/redis-data-types.html
  6. hyperLOGLOG原理
  7. Redis集群搭建的三种方式
  8. redis集群搭建(非常详细,适合新手)