nosql概述
为什么需要nosql
mysql
网站的瓶颈:
- 数据量太大,一台服务器存储空间不足
- 数据的索引(mysql使用B+ Tree)太大,一台服务器的内存不足
- 访问量(读写混合),一台服务器无法承受
Memcached(缓存) + Mysql + 垂直拆分(读写分离)
解决读的问题
分库分表 + 水平拆分 + mysql集群
解决写的问题:
- 早年MyISAM:表锁,影响效率
- InnoDB:行锁
- 使用分库分表解决写的压力
其他数据库
- 关系型数据库mysql
- 图形数据库
- MonoDB
- MongoDB
基本的架构
- 商品基本信息
- 名称、价格、商家信息
- mysql
- 描述、评论(文字较多)
- MongoDB
- 图片
- 分布式文件系统FastDFS
- TB TFS
- Google GFS
- Hadoop HDFS
- 阿里云 oss
- 商品关键字(搜索)
- 搜索引擎 solr ElasticSearch
- ISearch
- 商品热门的波段信息
- 内存数据库
- Redis、Memcache
- 商品交易,外部支付接口
- 三方应用接口
什么是nosql
NoSQL = Not Only SQL, 泛指非关系型数据库
nosql特点
- 方便扩展(数据之间没有关系)
- 大数据量高性能(Redis一秒写8w,读取11w,NoSQL的缓存级是一种细粒度的缓存)
- 数据类型多样性(不需要事先设计数据库,随取随用)
- String
- List
- Set
- Hash
- Zset
- geo
- hyperloglog
- bitmap
- 传统RDBMS和NoSQL
传统RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表里
- 严格的一致性
- 基础的事务
NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- CAP定理和BASE(异地多活)
- 三高:高性能,高可用,高可扩
- 三V:海量Volume,多样Variaty,实时Velocity
NoSQL四大分类
KV键值对
- 新浪:Redis
- 美团:Redis + Tair
- 阿里、百度:Redis + memecache
文档型数据库(bson格式 和json一样)
- MongoDB
- 是一个基于分布式文件存储的数据库,C++编写,主要用于处理大量文档
- 是一个介于关系型数据库和非关系型数据库之间的中间产品
- ConthDB
列存储数据库
- HBase
- 分布式文件系统
图关系数据库
- 存放关系
- 常用于广告推荐
- Neo4j,InfoGrid
Redis
- 内存存储、持久化(RDB、AOF),内存是断电即失
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量)
安装及使用
- 官网下载:Redis
- Linux系统下解压,然后
make
make install
// 如果make install提示失败,查看是否有权限在/usr/local/bin下写文件,使用sudo
- 配置文件,解压后的源文件夹下有
redis.conf,拷贝到方便的路径(本人是直接放在/usr/local/bin下),然后修改日志位置
- 启动服务器
cd /usr/local/bin
# 第二个参数是redis.conf的路径
./redis-server redis.conf
5. 启动客户端
推荐用sudo,否则可能因为日志文件和pid文件无权限写入导致异常运行
# -p为redis服务端绑定的端口号,-h为服务端的ip地址,如果为本机则可以不用, -a 为服务端密码
redis-cli -h host -p port -a password
连接成功
6. 关闭
shutdown // 关闭服务端
exit // 关闭客户端
- 常用命令
# 切换数据库,数据库默认有16个,在配置文件中
select 5
# 移动key到另一个数据库
move key index
# 查看数据库大小
dbsize
# 清空所有数据库
flushall
# 清空当前数据库
flushdb
- redis是单线程
性能测试工具
redis-benchmark
数据类型
- string
- string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
- string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
# 设置
set key value
# 获取
get key
# 获取子字符串
getrange key start end
# 获取并返回旧值
getset key value
# 获取指定偏移量上的位
getbit key offset
# 仅在key不存在时设置key的值
setnx key value
# 获取字符串长度
strlen key
# 从指定偏移覆写,不是全部擦除然后覆写
setrange key offset value
# 同时设置多个键值对
mset/msetnx key1 value1 key2 value2...
# 将key中存储的数字加1/加上指定值/浮点值,可为负,如果非数字会报错
incr key
incrby key increment
incrbyfloat key increment
decr key
decrby key increment
# 追加
append key value
- Hash(哈希)
- Redis hash 是一个键值(key=>value)对集合。
- Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
# 设置
hset/hsetnx key field value
# 设置多个键值对
HMSET myhash field1 hello field2 hi
# 获取字段对应值
HGET myhash field1
# 删除一个或多个字段
hdel key field1 [field2]
# 指定字段是否存在
hexists key field
# 获取所有字段和值
hgetall key
# 获取所有字段
hkeys key
# 获取给定字段的值
hmget key field [field]
# 获取所有字段的数量
hlen key
# 获取所有给定字段的值
hmget key field1 [field2]
# 给指定字段加上增量
hincrby/hincrbyfloat key field increment
- List(列表) 实际上是一个双向链表
# 从左边加入,可以一次加入多个,空格隔开
lpush listname element1 [elememt2]
# 从右边加入,可以一次加入多个,空格隔开
rpush listname element1 [elememt2]
# 移除并获取元素,如果没有元素会阻塞列表直到等待超时或发现可弹出元素,可多个key
blpop/brpop key1 [key2] timeout
# 弹出最后一个元素,并放入另个列表中
brpoplpush source des timeout # 会阻塞
rpoplpush source des # 不阻塞
# 通过索引获取
lindex key index
# 获取长度
llen key
# 在元素前/后插入
linsert key before/after pivot value
# 弹出
lpop/rpop key
# 移除指定元素,最多count个,count为0则移除所有
lrem key count value
# 通过索引设置,超出已有范围会报错
lset index value
# 查询列表
lrange listname 起始索引 终点索引
# 修剪,只保留指定区间内的元素
ltrim key start stop
- Set(集合)
# 添加member到key对应的集合里,返回成功的个数
sadd key member1 [member2]
# 获取个数
scard key
# 获取第一个集合与其他集合差异(key1有而其他无)
sdiff key1 [key2]
# 获取第一个集合与其他集合差异(key1有而其他无)并存储(会把原来的全部覆盖掉)
sdiffstore des key1 [key2]
# 获取交集
sinter key1 [key2]
# 获取交集并存储(会把原来的全部覆盖掉)
sinterstore des key1 [key2]
# 查询集合
smembers key
# 查询是否成员
sismember key member
# 将member移动
smove source des member
# 移除并返回随机元素
spop key
# 返回一或多随机数
srandmember key [count]
# 移除成员
srem key mem1 [mem2]
# 并集
sunion key1 [key2]
# 并集并存储
sunionstore des key1 [key2]
- zset(sorted set: 有序集合)
-
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
-
不同的是每个元素都会关联一个double类型的
score。redis正是通过score来为集合中的成员进行从小到大的排序。 -
zset的成员是唯一的,但分数(score)却可以重复
# 添加元素到集合,元素在集合中则更新对应的score
zadd key score member [score2 mem2]
# 获取成员数量
zcard key
# 获取分数在指定区间的成员数量
zcount key min max
# 指定成员分数增加inc
zincrby key inc member
# 获取交集并存储
zinterstore des keynum key1 [key2]
# 获根据字典区间
# [min 表示返回的结果中包含 min 值
# [max 表示返回的结果中包含 max 值
# (min 表示返回的结果中不包含 min 值
# (max 表示返回的结果中不包含 max 值
# -表示得分最小值的成员
# +表示得分最大值的成员
zlexcount key min max
# 通过索引列出所有成员
# 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
# 可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推
zrange key start stop [byscore/bylex] [rev] [withscores]
zrevrange key start stop
# 返回指定成员的索引
zrank key member
# 移除
zrem key member [member1]
zremrangebylex key min max
zremrangebyrank key strat stop
zremrangebyscore key min max
# 返回反转的排名
zrevrank key member
# 计算并集并存储
zunionstore des kenum key [key2]
redis的key命令(key区分大小写)
- del key
- dump key
- 序列化给定key,返回被序列化的值
- exists key
- expire key seconds/milliseconds
- 为key设置过期时间,以秒/毫秒计
- expire key timestamp/milliseconds-timestamp
- 为key设置过期时间,接收的时间参数为unix时间戳/毫秒时间戳
- keys pattern
- 搜索所有符合给定模式的key,*表示所有
- PTTL/TTL key
- 返回key的剩余过期时间,以毫秒/秒为时间
- RANDOMKEY
- 随机返回一个key
- rename key newkey
- 如果newkey存在,也会进行覆盖,不管类型是否相同
- renamenx key newkey
- 仅当newkey不存在时,将key改为newkey
- type key
发布订阅
psubscribe pattern [pattern2]
# subcommand = channels
pubsub subcommand [arg]
publish channel mes
punsubscribe pattern [patterb2]
subscribe channel [channel1]
unsubscribe channel [channel1]
redis事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
- 开始事务。
- 命令入队。
- 执行事务。
multi
set name lilia
get name
sadd attr 19 female hust
smembers attr
exec
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
其他指令:
# 取消事务,放弃已输入的所有命令
discard
watch key [key1]
unwatch