MySQL
- 数据库系统解决的问题:持久化存储,优化读写,保证数据的有效性
- 当前使用的数据库,主要分为两类
- 文档型,如sqlite,就是一个文件,通过对文件的复制完成数据库的复制
- 服务型,如mysql、postgre,数据存储在一个物理文件中,但是需要使用终端以tcp/ip协议连接,进行数据库的读写操作
E-R模型
- 当前物理的数据库都是按照E-R模型进行设计的
- E表示entry,实体
- R表示relationship,关系
- 一个实体转换为数据库中的一个表
- 关系描述两个实体之间的对应规则,包括
- 一对一
- 一对多
- 多对多
- 关系转换为数据库表中的一个列 *在关系型数据库中一行就是一个对象
三范式
- 第一范式(1NF):列不可拆分
- 第二范式(2NF):唯一标识
- 第三范式(3NF):引用主键
说明:后一个范式,都是在前一个范式的基础上建立的
安装
ubuntu中先切换到root账户,sudo -s
,然后
sudo apt-get install mysql-server mysql-client
管理服务
- 启动
service mysql start
- 停止
service mysql stop
- 重启
service mysql restart
允许远程访问
- 找到mysql配置文件并修改
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
将bind-address=127.0.0.1
注释 - 登录mysql,运行命令
grant all privileges on *.* to 'root'@'%' identified by 'mysql' with grant option;
flush privileges;
- 重启mysql
登录
mysql -uroot -p
####退出
exit;
或quit
字段类型
- 数字:int,decimal(小数),如decimal(5,2)一共5位数,小数位2位
- 字符串:char,varchar,text
- 日期:datetime
- 布尔:bit
约束
- 主键primary key
- 非空not null
- 唯一unique
- 默认default
- 外键foreign key
命令脚本操作
远程连接
mysql -hip地址 -uroot -p
数据库操作
- 创建数据库
create database 数据库名 charset=utf8;
- 删除数据库
drop database 数据库名;
- 切换数据库
use 数据库名;
- 查询当前使用的数据库
select database();
- 显示所有的数据库
show databases;
表操作
- 查看所有表
show tables;
- 创建表
- 创建数据库
create table 表名(列及类型);
如:
create table students(
id int auto_increment primary key,
sname varchar(10) not null
);
- 修改表
alter table 表名 add|change|drop 列名 类型;
- 删除表
drop table 表名;
- 查看表结构
desc 表名;
- 更改表名称
rename table 原表名 to 新表名;
- 查看表的创建语句
show create table '表名';
数据操作
- 查询
select * from 表名
- 增加
全列插入:insert into 表名 values(...)
缺省插入:insert into 表名(列1,...) values(值1,...)
同时插入多条数据:insert into 表名 values(...),(...)...;
或insert into 表名(列1,...) values(值1,...),(值1,...)...;
- 修改
update 表名 set 列1=值1,... where 条件
- 删除
delete from 表名 where 条件
- 逻辑删除
本质就是修改操作update
数据备份
- 进入管理员
sudo -s
- 进入mysql库目录
cd /var/lib/mysql
- 运行mysqldump命令
mysqldump –uroot –p 数据库名 > ~/Desktop/备份文件.sql;
数据恢复
- 连接mysqk,创建数据库
- 退出连接,执行如下命令
mysql -uroot –p 数据库名 < ~/Desktop/备份文件.sql
查询
- 消除重复行
select distinct gender from students;
条件
比较运算符
- 等于=
- 大于>
- 大于等于>=
- 小于<
- 小于等于<=
- 不等于!=或<>
逻辑运算符
- and
- or
- not
模糊查询
like
%
表示任意多个任意字符_
表示一个任意字符
范围查询
in
表示在一个非连续的范围内between ... and ...
表示在一个连续的范围内
空判断
- 注意:null与”是不同的
- 判空is null
优先级
- 小括号,not,比较运算符,逻辑运算符
- and比or先运算,如果同时出现并希望先算or,需要结合()使用
聚合
为了快速统计结果,提供了5个聚合函数。
- count
- max
- min
- sum
- avg
分组
分组的目的是为了聚合
- 按照字段分组,表示此字段相同的数据会被放到一个组中
- 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中
- 可以对分组后的数据进行统计,做聚合运算
语法select 列1,列2,聚合... from 表名 group by 列1,列2,列3...
select后面的列必须是在group by后面出现的列名。
比如select gender as 性别,count(*) from students group by gender;
分组后的数据筛选
- 语法
select 列1,列2,聚合... from 表名
group by 列1,列2,列3...
having 列1,...聚合...
- 对比where与having
where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
having是对group by的结果进行筛选
排序
- 语法
select * from 表名
order by 列1 asc|desc,列2 asc|desc,...
- 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
- 默认按照列值从小到大排列
- asc从小到大排列,即升序
- desc从大到小排序,即降序
分页
- 语法
select * from 表名
limit start,count
- 从start开始,获取count条数据
- start索引从0开始
总结
- 完整的查询语句
select distinct *
from 表名
where ....
group by ... having ...
order by ...
limit star,count
- 执行顺序
- from 表名
- where ….
- group by …
- select distinct *
- having …
- order by …
- limit star,count
连接查询
- 语法
inner join
select *
from tableName
inner join tableName2 on condition
inner join tableName3 on condition2 ...
- 左连接 表A left join 表B ,以左表为准,右边没有的数据以Null填充
- 右连接 表A right join 表B,以表B为准。
视图
- 视图本质就是对查询的一个封装。
create view view_name as
select * from tableName
where ...;
- 视图的用途就是查询
select * from view_name;
事务
- 当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回
- 使用事务可以完成退回的功能,保证业务逻辑的正确性
- 事务四大特性(简称ACID)
- 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行
- 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致
- 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的
- 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障
- 要求:表的类型必须是
innodb或bdb
类型,才可以对此表使用事务
查看表的创建语句
show create table 表名;
修改表的类型
alter table '表名' engine=innodb;
事务语句
开启begin;
提交commit;
回滚rollback;
索引
索引能提高数据库访问性能。
- 单列索引
- 组合索引
查看索引
show INDEX from tableName
创建索引
create INDEX indexName ON tableName(colName(length),colName2...)
删除索引
drop INDEX [indexName] ON tableName
缺点:
在执行更新操作时需要额外更新索引。
MySQL中测试执行时间
1、set profiling=1;
2、some operation
3、show profiles;show profile
与Python交互
Linux下安装
sudo apt-get install python-mysqldb
Mac下安装:
1、下载地址:https://sourceforge.net/projects/mysql-python
2、解压,cd到这个目录
3、sudo -s 切换到root用户
4、python setup.py install
遇到一些问题可以参考以下博客解决:http://www.cnblogs.com/ppsunlight/p/3817142.html
http://blog.csdn.net/u010499721/article/details/49048643
http://blog.csdn.net/wirelessqa/article/details/50506056
sudo install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib /Library/Python/2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.12-intel.egg/_mysql.so
引用
import Mysqldb
Connection对象
- 用于建立与数据库的连接
创建对象:调用connect()方法:
conn=connect(参数列表)
- 参数host:连接的mysql主机,如果本机是’localhost’
- 参数port:连接的mysql主机的端口,默认是3306
- 参数db:数据库的名称
- 参数user:连接的用户名
- 参数password:连接的密码
- 参数charset:通信采用的编码方式,默认是’gb2312’,要求与数据库创建时指定的编码一致,否则中文会乱码
对象的方法
- close()关闭连接
- commit()事务,所以需要提交才会生效
- rollback()事务,放弃之前的操作
- cursor()返回Cursor对象,用于执行sql语句并获得结果
Cursor对象
- 执行sql语句
- 创建对象:调用Connection对象的cursor()方法:
cursor1=conn.cursor()
对象的方法
- close()关闭
- execute(operation [, parameters ])执行语句,返回受影响的行数
- fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组
- next()执行查询语句时,获取当前行的下一行
- fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
- scroll(value[,mode])将行指针移动到某个位置
- mode表示移动的方式
- mode的默认值为relative,表示基于当前行移动到value,value为正则向下移动,value为负则向上移动
- mode的值为absolute,表示基于第一条数据的位置,第一条数据的位置为0
对象的属性
- rowcount只读属性,表示最近一次execute()执行后受影响的行数
- connection获得当前连接对象
SQL语句参数化
sname = '北京'
params=[sname] #list
count=cs1.execute('insert into areas(name) values(%s)',params)
MongoDB
NoSQL简介
- NoSQL,全名为Not Only SQL,指的是非关系型的数据库
- 随着访问量的上升,网站的数据库性能出现了问题,于是nosql被设计出来
优点
- 高可扩展性
- 分布式计算
- 低成本
- 架构的灵活性,半结构化数据
- 没有复杂的关系
缺点
- 没有标准化
- 有限的查询功能(到目前为止)
- 最终一致是不直观的程序
类型 | 部分代表 | 特点 |
---|---|---|
列存储 | Hbase、Cassandra、Hypertable | 顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。 |
文档存储 | MongoDB、CouchDB | 文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有有机会对某些字段建立索引,实现关系数据库的某些功能。 |
key-value存储 | Tokyo Cabinet / Tyrant、Berkeley DB、MemcacheDB、Redis | 可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能) |
图存储 | Neo4J、FlockDB | 图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。 |
对象存储 | db4o、Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据 |
xml数据库 | Berkeley DB XML、BaseX | 高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath。 |
基本信息
- MongoDB将数据存储为一个文档,数据结构由键值(key=>value)对组成
- MongoDB文档类似于JSON对象,字段值可以包含其他文档、数组、文档数组
MongoDB特点
- 模式自由 :可以把不同结构的文档存储在同一个数据库里
- 面向集合的存储:适合存储 JSON风格文件的形式
- 完整的索引支持:对任何属性可索引
- 复制和高可用性:支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目的是提供冗余及自动故障转移
- 自动分片:支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器
- 丰富的查询:支持丰富的查询表达方式,查询指令使用JSON形式的标记,可轻易查询文档中的内嵌的对象及数组
- 快速就地更新:查询优化器会分析查询表达式,并生成一个高效的查询计划
- 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)
名词
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table | joins | 表连接,MongoDB不支持 |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
三元素:数据库,集合,文档
- 集合就是关系数据库中的表
- 文档对应着关系数据库中的行
文档,就是一个对象,由键值对构成,是json的扩展Bson形式
{'name':'guojing','gender':'男'}
- 集合:类似于关系数据库中的表,储存多个文档,结构不固定,如可以存储如下文档在一个集合中
- 数据库:是一个集合的物理容器,一个数据库中可以包含多个文档
- 一个服务器通常有多个数据库
安装
- 下载mongodb的版本,两点注意
- 根据业界规则,偶数为稳定版,如1.6.X,奇数为开发版,如1.7.X
- 32bit的mongodb最大只能存放2G的数据,64bit就没有限制
- 到官网,选择合适的版本下载
- 解压
tar -zxvf mongodb.tgz
或者Mac上使用brew
安装brew install mongodb --with-openssl
- 移动到/usr/local/目录下
sudo mv -r mongodb-linux-x86_64-ubuntu1604-3.4.0/ /usr/local/mongodb
- 将可执行文件添加到PATH路径中
export PATH=/usr/local/mongodb/bin:$PATH
Mac下安装可以直接使用
brew update
,brew install mongodb
,然后使用mongod —config /usr/local/etc/mongod.conf
启动mongodb的服务
MongoDB官网https://www.mongodb.com/
管理mongo
- 配置文件在/etc/mongod.conf
- 默认端口27017
- 启动
sudo service mongod start
- 停止
sudo service mongod stop
- 使用终端连接
mongo
命令
db
查看当前数据库名称db.stats()
查看当前数据库信息show dbs
列出所有在物理上存在的数据库use 数据库名称
切换数据库。如果数据库不存在,则指向数据库,但不创建,直到插入数据或创建集合时数据库才被创建;默认的数据库为test,如果你没有创建新的数据库,集合将存放在test数据库中db.dropDatabase()
删除当前指向的数据库,如果数据库不存在,则什么也不做db.createCollection(name, options)
选项参数是可选的- 参数capped:默认值为false表示不设置上限,值为true表示设置上限
- 参数size:当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节
show collections
查看当前数据库的集合db.集合名称.drop()
删除集合
数据类型
- Object ID:文档ID
- String:字符串,最常用,必须是有效的UTF-8
- Boolean:存储一个布尔值,true或false
- Integer:整数可以是32位或64位,这取决于服务器
- Double:存储浮点值
- Arrays:数组或列表,多个值存储到一个键
- Object:用于嵌入式的文档,即一个值为一个文档
- Null:存储Null值
- Timestamp:时间戳
- Date:存储当前日期或时间的UNIX时间格式
object id
- 每个文档都有一个属性,为_id,保证每个文档的唯一性
- 可以自己去设置_id插入文档
- 如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectID
- objectID是一个12字节的十六进制数
- 前4个字节为当前时间戳
- 接下来3个字节的机器ID
- 接下来的2个字节中MongoDB的服务进程id
- 最后3个字节是简单的增量值
操作
插入
语法:db.集合名称.insert(document)
如db.test.insert({name:'bendeng'})
- 插入文档时,如果不指定_id参数,MongoDB会为文档分配一个唯一的ObjectId
简单查询
语法:db.集合名称.find()
更新
语法
db.集合名称.update(
<query>,
<update>,
{multi: <boolean>}
)
- 参数query:查询条件,类似sql语句update中where部分
- 参数update:更新操作符,类似sql语句update中set部分
- 参数multi:可选,默认是false,表示只更新找到的第一条记录,值为true表示把满足条件的文档全部更新
- 例:全文档更新
db.test.update({},{name:"newName"})
- 指定属性更新,通过操作符
$set
,db.test.update({},$set:{name:"newName"})
保存
语法:db.集合名称.save(document)
- 如果文档的_id已经存在则修改,如果文档的_id不存在则添加
删除
语法:
db.集合名称.remove(
<query>,
{
justOne: <boolean>
}
)
- 参数query:可选,删除的文档的条件
- 参数justOne:可选,如果设为true或1,则只删除一条,默认false,表示删除多条
如db.test.remove({_id:1234})
- 全部删除
db.stu.remove({})
数据查询
基本查询
db.集合名称.find({条件文档})
db.集合名称.findOne({条件文档})
只返回第一条db.集合名称.find({条件文档}).pretty()
将结果格式化
比较运算符
- 等于,默认是等于判断,没有运算符
- 小于$lt
- 小于或等于$lte
- 大于$gt
- 大于或等于$gte
- 不等于$ne
逻辑运算符
- 逻辑与:默认是逻辑与的关系
- 逻辑或:使用
$or
。db.stu.find({or:[{_id:{gt:18}},{name:”bendeng”}]}) - and和or一起使用
范围运算符
使用$in
,$nin
判断是否在某个范围内
db.test.find({_id:{$in:[18,28]}})
支持正则表达式
使用//
或$regex
编写正则表达式
db.test.find({name:/^p/})
db.test.find({name:{$regex:’^p’}}})
自定义查询
使用$where
后面写一个函数,返回满足条件的数据
db.test.find({$where:function(){return this.id>20}})
Limit
用于读取指定数量的文档
语法:db.集合名称.find().limit(NUMBER)
- 参数NUMBER表示要获取文档的条数
- 如果没有指定参数则显示集合中的所有文档
skip
用于跳过指定数量的文档
语法:db.集合名称.find().skip(NUMBER)
- 参数NUMBER表示跳过的记录条数,默认值为0
分页
- 方法limit()和skip()可以一起使用,不分先后顺序
投影
在查询到的返回结果中,只选择必要的字段,而不是选择一个文档的整个字段。如:一个文档有5个字段,需要显示只有3个,投影其中3个字段即可
语法:db.集合名称.find({},{字段名称:1,...})
- 参数为字段与值,值为1表示显示,值为0不显示
- 对于需要显示的字段,设置为1即可,不设置即为不显示
- 特殊:对于_id列默认是显示的,如果不显示需要明确设置为0db.test.find({},{_id:0})
排序
语法:db.集合名称.find().sort({字段:1,...})
- 参数1为升序排列
- 参数-1为降序排列
如:db.test.find().sort({name:1})
,结果是:
{ "_id" : ObjectId("59e1c73d82debd5e42f2d81a"), "name" : "huhu" }
{ "_id" : ObjectId("59e1c73882debd5e42f2d819"), "name" : "kaixin" }
{ "_id" : ObjectId("59e1c61682debd5e42f2d818"), "name" : "newDocumanet" }
{ "_id" : ObjectId("59e1c74082debd5e42f2d81b"), "name" : "pupu" }
统计
语法:db.集合名称.find({条件}).count()
或者db.集合名称.count({条件})
例如:统计年龄大于20的男生人数
db.stu.count({age:{$gt:20},gender:1})
去重
语法:db.集合名称.distinct('去重字段',{条件})
高级操作
聚合
主要用于计算数据,类似sql中的sum()、avg()
语法:db.集合名称.aggregate([{管道:{表达式}}])
- 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入。如
ps ajx | grep mongo
- 在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理
- 常用管道:
- $group:将集合中的文档分组,可用于统计结果
- $match:过滤数据,只输出符合条件的文档
- $project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
- $sort:将输入文档排序后输出
- $limit:限制聚合管道返回的文档数
- $skip:跳过指定数量的文档,并返回余下的文档
- $unwind:将数组类型的字段进行拆分
如:db.test.aggregate([{$group:{_id:'$name',c:{$sum:1}}}])
这里将name字段进行group分组,并查出每个名字的个数。
结果是
{ "_id" : "panpan", "c" : 3 }
{ "_id" : "pupu", "c" : 1 }
{ "_id" : "huhu", "c" : 1 }
{ "_id" : "kaixin", "c" : 1 }
{ "_id" : "newDocumanet", "c" : 1 }
表达式:’$列名’
- 常用表达式
- sum:计算总和, sum:1同count表示计数
- $avg:计算平均值
- $min:获取最小值
- $max:获取最大值
- $push:在结果文档中插入值到一个数组中
- $first:根据资源文档的排序获取第一个文档数据
- $last:根据资源文档的排序获取最后一个文档数据
索引
- 建立唯一索引,实现唯一约束的功能
db.test.ensureIndex({"name":1})
- 联合索引,对多个属性建立一个索引
db.test.ensureIndex({"name":1},{"gender":1})
- 查看文档的所有索引
db.test.getIndexes()
- 删除索引
db.test.dropIndex({"name":1})
db.test.ensureIndexes()
安全管理
- 为了更安全的访问mongodb,需要访问者提供用户名和密码,于是需要在mongodb中创建用户
- 采用了
角色-用户-数据库
的安全管理方式 - 常用系统角色如下:
- root:只在admin数据库中可用,超级账号,超级权限
- Read:允许用户读取指定数据库
- readWrite:允许用户读写指定数据库
- 创建超级管理用户
use admin
db.createUser({
user:'admin',
pwd:'123',
roles:[{role:'root',db:'admin'}]
})
启用安全认证
- 修改配置文件
sudo vi /etc/mongod.conf
- 启用身份验证(注意:keys and values之间一定要加空格, 否则解析会报错)
security:
authorization: enabled - 重启服务
sudo service mongod stop
sudo service mongod start - 终端连接
mongo -u 'admin' -p '123' --authenticationDatabase 'admin'
- 修改用户:可以修改pwd、roles属性`db.updateUser(‘admin’,{pwd:’456’})
复制(副本集)
- 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并可以保证数据的安全性
- 复制还允许从硬件故障和服务中断中恢复数据
为什么要复制
- 数据备份
- 数据灾难恢复
- 读写分离
- 高(24* 7)数据可用性
- 无宕机维护
- 副本集对应用程序是透明
复制的工作原理
- 复制至少需要两个节点A、B…
- A是主节点,负责处理客户端请求
- 其余的都是从节点,负责复制主节点上的数据
- 节点常见的搭配方式为:一主一从、一主多从
- 主节点记录在其上的所有操作,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致
- 主节点与从节点进行数据交互保障数据的一致性
复制的特点
- N 个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
步骤
- step1:创建数据库目录t1、t2
- step2:使用如下格式启动mongod,注意replSet的名称是一致的
mongod --bind_ip 192.168.196.128 --port 27017 --dbpath ~/Desktop/t1 --replSet rs0
mongod --bind_ip 192.168.196.128 --port 27018 --dbpath ~/Desktop/t2 --replSet rs0
- step3:连接主服务器,此处设置192.168.196.128:27017为主服务器
mongo --host 192.168.196.128 --port 27017
- step4:初始化
rs.initiate()
- step5:查看当前状态
rs.status()
- step6:添加复本集
rs.add('192.168.196.128:27018')
- step7:复本集添加成功
- step8:连接第二个mongo服务
mongo --host 192.168.196.128 --port 27018
- step9:向主服务器中插入数据
- step10:在从服务器中插查询
- 说明:如果在从服务器上进行读操作,需要设置
rs.slaveOk()
rs.slaveOk()
db.t1.find()
其它
- 删除从节点rs.remove('192.168.196.128:27018')
- 关闭主服务器后,再重新启动,会发现原来的从服务器变为了从服务器,新启动的服务器(原来的从服务器)变为了从服务器
备份
语法:mongodump -h dbhost -d dbname -o dbdirectory
- -h:服务器地址,也可以指定端口号
- -d:需要备份的数据库名称
- -o:备份的数据存放位置,此目录中存放着备份出来的数据
例如:
sudo mkdir test1bak
sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak
恢复
语法:mongorestore -h dbhost -d dbname --dir dbdirectory
- -h:服务器地址
- -d:需要恢复的数据库实例
- -dir:备份数据所在位置
例如
mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1
与Python的交互
查看官方文档
安装pymongo:pip install pymongo
Mac中安装使用
sudo python -m pip install pymongo
- 引入包pymongo
import pymongo - 连接,创建客户端
client=pymongo.MongoClient(“localhost”, 27017) - 获得数据库test
db=client.test - 获得集合test
test = db.test - 添加文档
s1={name:’gj’,age:18}
s1_id = test.insert_one(s1).inserted_id - 查找一个文档
s2=test.find_one() - 查找多个文档1
for cur in test.find():
print cur - 查找多个文档2
cur=test.find()
cur.next()
cur.next()
cur.next() - 获取文档个数
print test.count()
Redis
安装
1、去Redis官网下载最新的稳定版。目前是4.0.2。curl -O http://download.redis.io/releases/redis-4.0.2.tar.gz
2、解压tar zxvf redis-4.0.2.tar.gz
3、复制:推荐放到usr/local目录下
sudo mv -r redis-3.2.3/* /usr/local/redis/
进入redis目录
cd /usr/local/redis/
4、sudo make
,sudo make test
5、安装:将redis的命令安装到/usr/bin/目录。sudo make install
6、运行redis-server
,按Ctrl+C停止
7、启动客户端:在新终端中运行如下代码。redis-cli
配置
- 在源文件/usr/local/redis目录下,文件redis.conf为配置文件
- 绑定地址:如果需要远程访问,可将此行注释
bind 127.0.0.1
- 端口,默认为6379
port 6379
- 是否以守护进程运行
- 如果以守护进程运行,则不会在命令行阻塞,类似于服务
- 如果以非守护进程运行,则当前终端被阻塞,无法使用
- 推荐改为yes,以守护进程运行
daemonize no|yes
- 数据文件
dbfilename dump.rdb
- 数据文件存储路径
dir的默认值为./,表示当前目录。推荐改为:dir /var/lib/redis
- 使用配置文件方式启动
- 直接运行redis-server会直接运行,阻塞当前终端
- 一般配置文件都放在/etc/目录下
sudo cp /usr/local/redis/redis.conf /etc/redis/
- 推荐指定配置文件启动
sudo redis-server /etc/redis/redis.conf
- 停止redis服务
ps ajx|grep redis
sudo kill -9 redis的进程id
数据操作
- redis是key-value的数据,所以每个数据都是一个键值对
- 键的类型是字符串
- 值的类型分为五种:
- 字符串string
- 哈希hash
- 列表list
- 集合set
- 有序集合zset
string
- string是redis最基本的类型
- 最大能存储512MB数据
- string类型是二进制安全的,即可以为任何数据,比如数字、图片、序列化对象等
命令
- 设置键值
set key value
- 获取键值
get key
- 设置键值及过期时间,以秒为单位
SETEX key seconds value
- 设置多个键值
MSET key value [key value ...]
- 获取多个键值
MGET key [key ...]
- 将值加1
INCR key
- 将key对应的value加整数
INCRBY key increment
- 将key对应的value减1
DECR key
- 将key对应的value减整数
DECRBY key decrement
- 追加值
APPEND key value
- 获取值长度
STRLEN key
键命令
- 查找键,参数支持正则
KEYS pattern
比如KEYS *
- 判断键是否存在,如果存在返回1,不存在返回0
EXISTS key [key ...]
- 查看键对应的value的类型
TYPE key
- 删除键及对应的值
DEL key [key ...]
- 设置过期时间,以秒为单位
EXPIRE key seconds
- 查看有效时间,以秒为单位
TTL key
hash
- hash用于存储对象,对象的格式为键值对
- 设置单个属性
HSET key field value
- 设置多个属性
HMSET key field value [field value ...]
- 获取一个属性的值
HGET key field
- 获取多个属性的值
HMGET key field [field ...]
- 获取所有属性的值
HGETALL key
- 获取所有的属性
HKEYS key
- 返回包含属性的个数
HLEN key
- 获取所有值
HVALS key
- 判断属性是否存在
HEXISTS key field
- 删除属性及值
HDEL key field [field ...]
- 返回值的字符串长度
HSTRLEN key field
list
- 列表的元素类型为string
- 按照插入顺序排序
- 在列表的头部或者尾部添加元素
- 在头部插入数据
LPUSH key value [value ...]
- 在尾部插入数据
RPUSH key value [value ...]
- 在一个元素的前|后插入新元素
LINSERT key BEFORE|AFTER pivot value
- 设置指定索引的元素值,索引是基于0的下标
- 索引可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LSET key index value
- 移除并且返回 key 对应的 list 的第一个元素
LPOP key
- 移除并返回存于 key 的 list 的最后一个元素
RPOP key
- 返回存储在 key 的列表里指定范围内的元素,start 和 end 偏移量都是基于0的下标,偏移量也可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LRANGE key start stop
- 裁剪列表,改为原集合的一个子集,start 和 end 偏移量都是基于0的下标,偏移量也可以是负数,表示偏移量是从list尾部开始计数,如-1表示列表的最后一个元素
LTRIM key start stop
- 返回存储在 key 里的list的长度
LLEN key
- 返回列表里索引对应的元素
LINDEX key index
无序集合set
- 元素为string类型
- 元素具有唯一性,不重复
- 添加元素
SADD key member [member ...]
- 返回key集合所有的元素
SMEMBERS key
- 返回集合元素个数
SCARD key
- 求多个集合的交集
SINTER key [key ...]
- 求某集合与其它集合的差集
SDIFF key [key ...]
- 求多个集合的合集
SUNION key [key ...]
- 判断元素是否在集合中
SISMEMBER key member
有序集合zset
- 元素为string类型
- 元素具有唯一性,不重复
- 每个元素都会关联一个double类型的score,表示权重,通过权重将元素从小到大排序
- 元素的score可以相同
- 添加
ZADD key score member [score member ...]
- 返回指定范围内的元素
ZRANGE key start stop
- 返回元素个数
ZCARD key
- 返回有序集key中,score值在min和max之间的成员
ZCOUNT key min max
- 返回有序集key中,成员member的score值
ZSCORE key member
高级
发布订阅
- 发布者不是计划发送消息给特定的接收者(订阅者),而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅
- 订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的
- 发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑
- 客户端发到频道的消息,将会被推送到所有订阅此频道的客户端
- 客户端不需要主动去获取消息,只需要订阅频道,这个频道的内容就会被推送过来
消息格式
- 推送消息的格式包含三部分
- part1:消息类型,包含三种类型
- subscribe,表示订阅成功
- unsubscribe,表示取消订阅成功
- message,表示其它终端发布消息
- 如果第一部分的值为subscribe,则第二部分是频道,第三部分是现在订阅的频道的数量
- 如果第一部分的值为unsubscribe,则第二部分是频道,第三部分是现在订阅的频道的数量,如果为0则表示当前没有订阅任何频道,当在Pub/Sub以外状态,客户端可以发出任何redis命令
- 如果第一部分的值为message,则第二部分是来源频道的名称,第三部分是消息的内容
命令
- 订阅
SUBSCRIBE 频道名称 [频道名称 ...]
- 取消订阅(如果不写参数,表示取消所有订阅)
UNSUBSCRIBE 频道名称 [频道名称 ...]
- 发布
PUBLISH 频道 消息
主从配置
- 一个master可以拥有多个slave,一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架构
- 比如,将ip为192.168.1.10的机器作为主服务器,将ip为192.168.1.11的机器作为从服务器
- 设置主服务器的配置
bind 192.168.1.10
- 设置从服务器的配置(注意:在slaveof后面写主机ip,再写端口,而且端口必须写)
bind 192.168.1.11
slaveof 192.168.1.10 6379
- 在master和slave分别执行info命令,查看输出信息
- 在master上写数据
set hello world
- 在slave上读数据
get hello
- 在master上写数据
与python交互
安装
sudo pip install redis
或者使用源码安装
unzip redis-py-master.zip
cd redis-py-master
sudo python setup.py install
使用
import redis
try:
r=redis.StrictRedis(host='localhost',port=6379)
except Exception,e:
print e.message
- 方式一:根据数据类型的不同,调用相应的方法,完成读写
r.set('name','hello')
r.get('name')
- 方式二:pipline
- 缓冲多条命令,然后一次性执行,减少服务器-客户端之间TCP数据库包,从而提高效率
pipe = r.pipeline()
pipe.set('name', 'world')
pipe.get('name')
pipe.execute()
封装
import redis
class RedisHelper():
def __init__(self,host='localhost',port=6379):
self.__redis = redis.StrictRedis(host, port)
def get(self,key):
if self.__redis.exists(key):
return self.__redis.get(key)
else:
return ""
def set(self,key,value):
self.__redis.set(key,value)