NoSQL(Not Only SQL), 泛指非关系型数据库,它的出现告诉我们:适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储。
关系型数据库的性能非常高,但是它毕竟是一个通用型的数据库,并不能完全适应所有的用途,具体来说它并不擅长以下处理:
- 大量数据的写入处理
- 为有数据更新的表做索引或表结构变更
- 字段不固定时应用
- 对简单查询需要快速返回结果的处理
这里逐一进行说明:
1. 大量数据的写入处理
在数据读入方面,由复制产生的主从模式(数据的写入由主数据库负责,数据的读入由从数据库负责),可以比较简单的通过增加从数据库来实现规模化,但是在数据库的写入方面却不是这么简单,例如,考虑把主数据库从一台增加到俩台,做为互相关联复制的二元主数据库来使用,确实这样似乎可以把每台主数据库的负荷减少一半,但是更新处理会发生冲突(同样的数据在俩台服务器同时更新成其他值),可能会造成数据的不一致,为了避免这样的问题,就需要把对某个表的请求分别分配给合适的的主数据库来处理。
另外也可以考虑把数据库分割开来,分别放在不同的数据库服务器上。数据库分割可以减少每台数据库服务器上的数据量,以便减少磁盘 I/O 处理,实现内存上的高速处理。但是这样做存储在不同服务器上的表之间就无法进行 join 处理。
2. 为有数据更新的表做索引或表结构变更
在使用关系型数据库时,为了加快查询速度需要创建索引,为了增加必要的字段就一定需要改变表结构。为了进行这些处理,需要对表进行共享锁定,这期间数据变更(更新,插入,删除)是无法进行的。如果为数据量比较大的表创建索引或者是变更其表结构,就可能会导致长时间内数据无法进行更新。
3. 字段不固定时的应用
如果字段不固定,在实际运用中每次都进行反复的表结构变更时非常痛苦的,也可以预先设定大量的预备字段,但这样的话很容易弄不清楚字段和数据的对应状态。
4. 对简单查询需要快速返回结果的处理
关系型数据库并不擅长对简单的查询快速返回结果,因为关系型数据库是使用 SQL 进行读取的,它需要对 SQL 语言进行解析,同时还有对表的的锁定和解锁这样的额外开销。若希望对简单查询进行高速处理,没有必要非用关系型数据库不可。
RDBMS | NoSQL |
---|---|
遵循 ACID 原则 (原子性,一致性,独立性,持久性) | BASE 原则 (基本可用,软状态 / 柔性事务, 最终一致性) |
结构化查询语言 (SQL) | 没有标准统一的查询语言 |
高度组织化结构化数据 | 非结构化和不可预知的数据 |
CAP 定理 |
在计算机科学中, CAP 定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
- 一致性 (Consistency) (所有节点在同一时间具有相同的数据)
- 可用性 (Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍 (Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
CAP 理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三大类:
- CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
- CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
- AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
类型 | 部分代表 | 特点 |
---|---|---|
列存储 | Hbase Cassandra Hypertable |
按列存储数据。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的 IO 优势 |
文档存储 | MongoDB CouchDB |
文档存储一般用类似 json 的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能 |
key-value 存储 | Redis MemcacheDB |
可以通过 key 快速查询到其 value。一般来说,存储不管 value 的格式,照单全收 |
图存储 | Neo4J FlockDB |
图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便 |
对象存储 | db4o Versant |
通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据 |
xml 数据库 | BaseX | 高效的存储 XML 数据,并支持 XML 的内部查询语法,比如 XQuery,Xpath |
Memcached 是一个自由开源的, 高性能,分布式内存对象缓存系统。本质上,它是一个简洁的 key-value 存储系统。一般使用的目的是通过缓存数据库查询结果,减少数据库访问次数,以提高动态 web 应用的速度,提高可扩展性。
memcached 的特征:
- 协议简单
memcached 的服务器客户端通信使用简单的基于文本行的协议,因此,通过 telnet 也能在 memcached 上保存数据,取得数据。
memcached 的分布式方法主要有俩种:取模法和一致性 hash 算法。
- CRC($key)%N
该算法下,客户端首先根据 key 来计算 CRC,然后结果对服务器数进行取模得到 memcached 服务器节点,这种方式有两个问题需要注意:
1. 当选择到的服务器无法连接的时候,一种解决办法是将尝试的连接次数加到 key 后面,然后重新进行 hash,这种做法也叫 rehash。
2. 第二个问题也是这种方法的致命的缺点,尽管余数计算分散发相当简单,数据分散也很优秀,当添加或者移除服务器的时候,缓存重组的代价相当大。
Memcached 官方并未提供 Windows 平台安装包,这里我使用的是菜鸟教程提供的安装包:
64 位系统 1.4.4 版本:
更多版本请参考
1. 解压下载的安装包到自定义目录。
2. 使用管理员权限运行一下命令进行安装:
- E:\memcached>memcached.exe -d install
可设置如下参数:
-p 监听的端口,默认是 11211
-l 连接的 IP 地址, 默认是本机
-d start 启动 memcached 服务
-d restart 重起 memcached 服务
-d stop|shutdown 关闭正在运行的 memcached 服务
-d install 安装 memcached 服务
-d uninstall 卸载 memcached 服务
-u 以的身份运行 (仅在以 root 运行的时候有效)
-m 最大内存使用,单位 MB。默认 64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是 1024
-f 块大小增长因子,默认是 1.25
-n 最小分配空间,key+value+flags 默认是 48
-h 显示帮助
如:
。 3. 使用以下命令来启动和关闭 memcached 服务:
- memcached -d install -l 127.0.0.1 -m 1024 -c 2048
- E:\memcached>memcached.exe -d start
- E:\memcached>memcached.exe -d stop
通过 telnet 命令并指定主机 IP 和端口来连接 Memcached 服务, 默认运行的主机为 127.0.0.l, 端口为 11211:
- telnet 127.0.0.1 11211
进入 telnet 窗口发现输入的字符无法显示,没关系,使用快捷键 Ctrl+] 就能显示出来了,然后输入
回车启用本地回显,再按一次回车进入 telnet 新窗口。输入 stats,查看 memcached 的状态:
- set localecho
- [command] key flags exptime bytes [noreply]
- vlaue
参数说明如下
参数 | 说明 |
---|---|
[command] | set/add/replace/append/prepend |
key | 查找键值 |
flags | 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 。 |
exptime | 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) |
bytes | 在缓存中存储的字节数 |
noreply | 可选,该参数告知服务器不需要返回数据 |
value | 存储的值(始终位于第二行) |
- set mykey 0 0 3
- 123
- STORED
- get mykey
- VALUE mykey 0 3
- 123
- END
- add mykey 0 0 3
- 456
- NOT_STORED
- add mykey2 0 0 4
- abcd
- STORED
- get mykey2
- VALUE mykey2 0 4
- abcd
- END
- replace mykey 0 900 3
- 456
- STORED
- get mykey
- VALUE mykey 0 3
- 456
- END
- replace mykey3 0 0 3
- 123
- NOT_STORED
- set mykey 0 0 3
- 123
- STORED
- append mykey 0 0 4
- abcd
- STORED
- prepend mykey 0 0 3
- xyz
- STORED
- get mykey
- VALUE mykey 0 10
- xyz123abcd
- END
,清理所有缓存:
- delete key
更多指令请参考
- flush_all [time] [noreply]
首先安装 PHP Memcache 扩展,运行 phpinfo() 查看 PHP 的版本信息,决定扩展文件版本:
在 下载正确版本的 php_memcache.dll 动态链接库文件 ,并放在 php\ext 目录下 。
编辑 php.ini,添加下面一行代码到 php.ini 文件中。
在 phpinfo 中查看 memcache 扩展是否安装成功:
- extension=php_memcache.dll
- <?php
- $memcache = new Memcache; //创建一个memcache对象
- $memcache->connect('localhost', 11211) or die ("Could not connect"); //连接Memcached服务器
- $memcache->set('key', 'hello,测试memcache成功'); //设置一个变量到内存中,名称是key 值是test
- $get_value = $memcache->get('key'); //从内存中取出key的值
- echo $get_value;
Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
- Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
- Redis 支持数据的备份,即 master-slave 模式的数据备份。
Redis 运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样 Redis 可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
redis 提供了两种持久化的方式,分别是 RDB(Redis DataBase)和 AOF(Append Only File)。
RDB,简而言之,就是在不同的时间点,将 Redis 存储的数据生成快照并存储到磁盘等介质上;
AOF,则是换了一个角度来实现持久化,那就是将 Redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
其实 RDB 和 AOF 两种方式也可以同时使用,在这种情况下,如果 redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。
如果你没有数据持久化的需求,也完全可以关闭 RDB 和 AOF 方式,这样的话,redis 将变成一个纯内存数据库,就像 memcache 一样。
这里不做深究,详情持久化的方式可以参考
Windows 下安装的下载地址为, 下载相应的压缩包解压重命名为 redis。
cmd 窗口运行
:
- redis-server.exe redis.windows.conf
设置键值对
- redis-cli.exe -h 127.0.0.1 -p 6379
, 取出键值对
- set mykey 123
:
- get mykey
Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 zset(sorted set:有序集合)。
命令 | 行为 |
---|---|
set key value | 设置指定 key 的值 |
get key | 获取指定 key 的值 |
del key | 在 key 存在是删除 key(这个命令可以用于所有类型) |
- 127.0.0.1:6379> set str_name "abc"
- OK
- 127.0.0.1:6379> get str_name
- "abc"
命令 | 行为 |
---|---|
hset key field value | 将哈希表 key 中的字段 field 的值设为 value |
hmset key field1 value1 [field2 value2] | 同时将多个 field-value (域 - 值) 对设置到哈希表 key 中 |
hget key field | 获取存储在哈希表中指定字段的值 |
hmget key field1 [field2] | 获取所有给定字段的值 |
hgetall key | 获取在哈希表中指定 key 的所有字段和值 |
hdel key field1 [field2] | 删除一个或多个哈希表字段 |
- 127.0.0.1:6379> hmset hash_key name htdwade passwd 123456 addr abc
- OK
- 127.0.0.1:6379> get hash_key
- (error) WRONGTYPE Operation against a key holding the wrong kind of value
- 127.0.0.1:6379> hgetall hash_key
- 1) "name"
- 2) "htdwade"
- 3) "passwd"
- 4) "123456"
- 5) "addr"
- 6) "abc"
命令 | 行为 |
---|---|
lpush key value1 [value2] | 将一个或多个值插入到列表头部 |
rpush key value1 [value2] | 在列表中添加一个或多个值 |
lpop key | 移出并获取列表的第一个元素 |
rpop key | 移除并获取列表最后一个元素 |
lindex key index | 通过索引获取列表中的元素 |
lrange key start stop | 获取列表指定范围内的元素 |
- 127.0.0.1:6379> lpush list_key php
- (integer) 1
- 127.0.0.1:6379> lpush list_key java
- (integer) 2
- 127.0.0.1:6379> rpush list_key c++
- (integer) 3
- 127.0.0.1:6379> lrange list_key 0 10
- 1) "java"
- 2) "php"
- 3) "c++"
命令 | 行为 |
---|---|
sadd key member1 [member2] | 向集合添加一个或多个成员 |
srem key member1 [member2] | 移除集合中一个或多个成员 |
smembers key | 返回集合中的所有成员 |
- 127.0.0.1:6379> sadd set_key a
- (integer) 1
- 127.0.0.1:6379> sadd set_key b
- (integer) 1
- 127.0.0.1:6379> sadd set_key b
- (integer) 0
- 127.0.0.1:6379> sadd set_key c
- (integer) 1
- 127.0.0.1:6379> smembers set_key
- 1) "b"
- 2) "c"
- 3) "a"
命令 | 行为 |
---|---|
zadd key score1 member1 [score2 member2] | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
zrem key member1 [member2] | 移除有序集合中的一个或多个成员 |
zrange key start stop [withscores] | 通过索引区间返回有序集合成指定区间内的成员 |
- 127.0.0.1:6379> zadd zset_key 2 mysql
- (integer) 1
- 127.0.0.1:6379> zadd zset_key 1 memcached
- (integer) 1
- 127.0.0.1:6379> zadd zset_key 3 nosql
- (integer) 1
- 127.0.0.1:6379> zrange zset_key 0 10
- 1) "memcached"
- 2) "mysql"
- 3) "nosql"
更多命令的使用请参考
首先安装 PHP Redis 扩展,运行 phpinfo() 查看 PHP 的版本信息,决定扩展文件版本.
在
下载正确版本的 php_redis.dll 和 php_igbinary.dll 动态链接库文件 ,并放在 php\ext 目录下 。
编辑 php.ini,添加下面代码到 php.ini 文件中。
- ;php_redis
- extension=php_igbinary.dll
- extension=php_redis.dll
注意:
一定要放在
- extension=php_igbinary.dll
的前面,否则此扩展不会生效。 在 phpinfo 中查看 redis 扩展是否安装成功:
- extension=php_redis.dll
- <?php
- //连接本地的 Redis 服务
- $redis = new Redis();
- $redis->connect('127.0.0.1', 6379);
- //设置 redis 字符串数据
- $redis->set("str_name", "hello ,这是一个string值");
- //获取存储的数据并输出
- echo $redis->get("str_name");
- echo "\n";
- //存储数据到列表中
- $redis->lpush("mlist_name", "Redis");
- $redis->lpush("mlist_name", "Mongodb");
- $redis->lpush("mlist_name", "Mysql");
- //获取存储的数据并输出
- $arrList = $redis->lrange("mlist_name", 0 ,5);
- var_dump($arrList);
来源: