NoSql的含义
NoSQL ,(Not Only SQL),泛指非关系型数据库, 它是由一次叫“反Sql运动”的社区讨论而诞生的体系。这个运动的发起最早源自于社区网站 LiveJournal的开发团队,它们的初衷是为了用于减少数据库连接数,减轻数据库的工作压力,但发展至今有着其他不同的应用领域,因此NoSQL处于一种所谓百家争鸣的,各执一词的时期。但我们作为NoSql的学习者和应用者,我们不需要关心和纠结这些NoSql的争论,也不需要参与到这些争论当中。
只要不是关系型数据库里面的东西,都可以叫做nosql数据库。
NoSql的共同特点和优势
- NoSQL 通常是以key-value形式存储的(如:Memcache、Redis、Mongodb)
- 不支持SQL语句
- 没有表结构
- 配置简单
- 灵活、高效的操作与数据模型(key-value存储,一般叫做hash表)
- 低廉的学习成本
- 能很好地作为MySql的中间层(cache is king 有缓存肯定会更好、缓存也会引来问题?数据 一致性的问题)
- 能很好地支持PHP
NoSql的共同的缺点
- 没有统一的标准
- 安全性极差(memcache没有权限系统 )
- 没有正式的官方支持 (社区维护)(GitHub)
- 各种产品还不算成熟
- 权威支持的产品价格很高(如:阿里云)
NoSql的产品分类
- 网站:http://www.nosql-database.org/
- redis
- mongodb
- memcache
- Aliyun MQ
- HBASE
- .....
Memcache
端口:11211
纯内存存储,是所有NoSQL产品中最简单,速度最快的,但也是功能最弱的
-
内置分布式算法,开发者不需要自己去实现
- 使用分布式存储数据
$mem = new Memcache(); $mem->addServer('127.0.0.1', 11212); $mem->addServer('127.0.0.1', 11213); $mem->addServer('127.0.0.1', 11214); # 数据自动分布在3台memcache服务器上,不用开发人员操心 for($i = 1; $i < 99; $i++){ $mem->set('key_' . $i, 'value_' . $i, 0, 86400); } echo "ok";
- 获取分布式数据
$mem = new Memcache(); $mem->addServer('127.0.0.1', 11212); $mem->addServer('127.0.0.1', 11213); $mem->addServer('127.0.0.1', 11214); # 开发人员无法得知数据的来源 $data = $mem->get('key_1'); var_dump($data);
-
可以设置数据有效期
Memcache设置缓存的有效期可以使用:
- 缓存时间:使用s秒数,但是不能超过86400*30s,也就是30天的秒数
- 时间戳:但是该方式只有在Linux下才可以使用,windows下不生效,使用时间戳可以设置大于30天的有效期
使用Telnet协议进行传输,没有加密功能,安全性很差,但在
内网
上影响不大最大存储空间只有64M,一旦爆满,Memcache会指定重启,并释放当前所有的内存
存储形式为KV型,单个Value值最大为1M(单个chunk最大为1M)
数据存储在内存中,一旦服务器维护或重启,数据就会丢失
数据零散,无法遍历,管理数据完整性非常一般
存储的数据都是字符串类型
-
可以配置Session共享(在php.ini中配置session.save_handler = memcache,session.save_path = "tcp://
#memcache服务器的IP#
:11211"); php.ini session.save_handler = memcache session.save_path = "tcp://127.0.0.1:11211"
-
Memcache的内存分配机制
由于Memcache是一个内存缓存系统,就涉及内存申请和释放的问题,不断的申请和释放内存,会导致内存的碎片化。为了解决内存碎片化的问题,Memcache使用了内存预先分配机制。
Memcache将64M的存储空间分割成64份,每一份都是1M的空间,这样的空间称为slab class。
slab class里面的存储数据的单元称为chunk,最小的chunk默认为96B,最大为1M。
相邻slab class之间chunk大小的比值是固定的,这个比值被称为增长因子,它可以根据实际的业务做相应的调整。
-
Memcache内部使用了LRU算法
LRU(Least Recently Used )算法被称为
最近最少使用原则
。 当memcache的一个slab里面的chunk不够使用的情况下(存储满了,数据在有效期)当有新的满足chunk的数据过来的情况下,memcache会优先把slab里面最近一段时间内,最不活跃的数据先剔除掉,腾出空间,给新的数据使用。
-
Memcache使用惰性删除机制
Memcache本身不监控数据是否过期,当下一次重新获取数据的时候,才会去查看数据是否有效,如果有效则返回,否则就清除。
-
Memcache实现高可用
- sina公司开发的MemcacheDB
- repcached:全称replication cached,是由日本人发明的memcache的高可用技术,简称复制缓冲区技术。
Redis
端口:6379
默认存在0~15共16个数据库
支持缓存数据持久化
-
支持5种数据类型
- String(字符串)
- list(链表)
- hash(哈希表)
- set(无序集合)
- sorted set(有序集合,缩写为zset)
为高并发而生
Redis使用一致性哈希虚拟节点算法可以实现分布式功能
存储形式为KV型,单个Value值最大可以存储1G的数据,存储总量可以视硬盘大小而定
-
Redis可以开启安全认证
# redis.conf # 由于配置文件中的密码是明文,所以一般会把该配置文件的权限设置为600 requirepass ##密码##(明文)
-
Redis的持久化
-
快照模式
默认模式,快照文件为dump.rdb。
当网站的数据量变大时,该文件也会随之增大,操作效率很低。
-
aof模式(append of file)
aof文件有点类似MySQL的binlog日志(读写分离)
aof文件会把用户的操作记录包括查询的过程全部记录,当服务器出现问题的时候,Redis会将数据从内存中保存到aof文件当中,当服务器重新运行时,Redis就会根据aof文件中的操作记录,把数据重新还原到内存当中去,以确保数据的完整性。
快照模式和aof模式是完全互斥的。
如果aof的模式一旦启动,那么快照就会失效,Redis就会把所有的数据缓存到内存当中,如果发生重启,停止,关闭服务器等行为,那么aof文件就会把内存中数据同步到硬盘中。
开启aof模式:
# redis.conf appendonly yes appendfilename "appendonly.aof" # appendfsync always # always 的选项代表Redis的命令每一次只要运行那么就会马上写入aof文件当中,该选项是最没有效率的,然而它却是最具备操作记录完整性的。 appendfsync everysec # everysec 的选项是Redis比较折中的选项,代表每一秒中只有有操作那么就会进行操作记录,但是如果在某一秒当中redis发生故障,那么这一秒的数据操作记录将有可能发生丢失的情况,存在一定的风险,然而这个配置的性能比较适中,所以建议使用 # appendfsync no # no 该配置的效率完全依赖您当前所在使用的操作系统和计算机的性能,如果操作系统稳定,计算机的性能强大,那么这一项是最有效率的,反而就是最差,所以一般最好不要设置该项
-
MongoDB
端口:27017
文档型数据库
存储的是经过特殊处理的json数据,也叫Bson(json二进制化后的数据)
MongoDB内部使用js解释引擎来实现数据的分析,在插入的时候,将数据转换成二进制的Bson来存储;在查询的时候,将数据Bson转换成json对象返回
-
存在数据库的概念
# 查看当前所有数据库 > show dbs; # 选择数据库 > use test; # 查看当前库下所有的数据表 > show tables; > show conllections; # 创建数据库 # MongoDB的数据库是隐式创建,当该数据库下有数据之后,它就会被自动创建了 # 删除当前数据库 > db.dropDatabase();
-
Collection(集合) → 相当于MySQL中的表
# 创建表 # 显式创建 > db.createConllection('collectionName'); # 隐式创建 > db.collectionName.insert(/*json数据*/); # 删除表 > db.collectionName.drop(); ####### 查找 # 查找所有 > db.collectionName.find(); # 将取出的数据以优雅的格式显式,链式调用 > db.collectionName.find().pretty(); # 按条件查找和展示 > db.collectionName.find({/*查询条件*/}, {/*要展示的字段*/}); # 例如:select age, name from stu where age > 18; > db.stu.find({'age':{$gt:18}}, {'_id':0, 'age':1, 'name':1}); # 只查询一条 # 例如:select age, name from stu where age > 18 limit 1; > db.stu.findOne({'age':{$gt:18}}, {'_id':0, 'age':1, 'name':1});
-
Document(文档) → 相当于MySQL表中的记录
####### 增加 > db.collectionName.insert(/*json数据*/); # 增加单条记录 > db.collectionName.insert({'name':'rico', 'age':19, 'gender':male}); # 增加多条记录 > db.collectionName.insert([ {'name':'rico', 'age':19, 'gender':male}, {'name':'nacy', 'age':22, 'gender':female, 'birthday':'1993/01/05'}, {'name':'zaks', 'age':30, 'gender':male, 'className':'php88'} ]); ####### 删除 > db.collectionName.remove(/*查询表达式*/, /*选项*/); # 例如:delete from stu where age < 10; > db.stu.remove({'name':{$gt:10}}); # 例如:delete from stu where age < 10 limit 1; > db.stu.remove({'name':{$gt:10}}, {justOne:true}); ####### 修改 > db.collectionName.update(/*查询表达式*/, /*新值*/); # 例如:update stu set name='coco' where _id=3; > db.stu.update({'_id':3}, {'name':'coco'}); # 注意:这里修改之后,文档中只有'_id'和'name'了 # 如果只是想修改某列,则可以使用$set > db.stu.update({'_id':3}, {$set:{'name':'coco'}}); ####### 分页 # 例如:select * from stu limit 5, 3; > db.stu.find().limit(3).skip(5); ####### 排序 # 例如:select * from stu order by age; > db.stu.find().sort({'age':1}); # 例如:select * from stu order by age desc; > db.stu.find().sort({'age':-1});
怎么关闭 mongoDB?千万不要 kill -9 pid,可以 kill -2 pid 或 db.shutdownServer()
-
mongodb的权限验证机制