Redis学习

53 阅读9分钟

nosql概述

为什么需要nosql

mysql

image.png 网站的瓶颈:

  1. 数据量太大,一台服务器存储空间不足
  2. 数据的索引(mysql使用B+ Tree)太大,一台服务器的内存不足
  3. 访问量(读写混合),一台服务器无法承受

Memcached(缓存) + Mysql + 垂直拆分(读写分离)

解决的问题 image.png

分库分表 + 水平拆分 + mysql集群

解决的问题: image.png

  • 早年MyISAM:表锁,影响效率
  • InnoDB:行锁
  • 使用分库分表解决写的压力

其他数据库

  • 关系型数据库mysql
  • 图形数据库
  • MonoDB
  • MongoDB

基本的架构

image.png

  1. 商品基本信息
  • 名称、价格、商家信息
  • mysql
  1. 描述、评论(文字较多)
  • MongoDB
  1. 图片
  • 分布式文件系统FastDFS
  • TB TFS
  • Google GFS
  • Hadoop HDFS
  • 阿里云 oss
  1. 商品关键字(搜索)
  • 搜索引擎 solr ElasticSearch
  • ISearch
  1. 商品热门的波段信息
  • 内存数据库
  • Redis、Memcache
  1. 商品交易,外部支付接口
  • 三方应用接口

什么是nosql

NoSQL = Not Only SQL, 泛指非关系型数据库

nosql特点
  1. 方便扩展(数据之间没有关系)
  2. 大数据量高性能(Redis一秒写8w,读取11w,NoSQL的缓存级是一种细粒度的缓存)
  3. 数据类型多样性(不需要事先设计数据库,随取随用)
    • String
    • List
    • Set
    • Hash
    • Zset
    • geo
    • hyperloglog
    • bitmap
  4. 传统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

image.png

Redis

  1. 内存存储、持久化(RDB、AOF),内存是断电即失
  2. 效率高,可以用于高速缓存
  3. 发布订阅系统
  4. 地图信息分析
  5. 计时器、计数器(浏览量)

安装及使用

  1. 官网下载:Redis
  2. Linux系统下解压,然后
make
make install
// 如果make install提示失败,查看是否有权限在/usr/local/bin下写文件,使用sudo
  1. 配置文件,解压后的源文件夹下有redis.conf,拷贝到方便的路径(本人是直接放在/usr/local/bin下),然后修改日志位置

image.png

  1. 启动服务器
cd /usr/local/bin

# 第二个参数是redis.conf的路径
./redis-server redis.conf

image.png 5. 启动客户端 推荐用sudo,否则可能因为日志文件和pid文件无权限写入导致异常运行

# -p为redis服务端绑定的端口号,-h为服务端的ip地址,如果为本机则可以不用, -a 为服务端密码
redis-cli -h host -p port -a password

连接成功 image.png 6. 关闭

shutdown // 关闭服务端
exit // 关闭客户端
  1. 常用命令
# 切换数据库,数据库默认有16个,在配置文件中
select 5
# 移动key到另一个数据库
move key index
# 查看数据库大小
dbsize
# 清空所有数据库
flushall
# 清空当前数据库
flushdb
  1. redis是单线程

性能测试工具

redis-benchmark

数据类型

  1. 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
  1. 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
  1. 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
  1. 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]
  1. 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区分大小写)

  1. del key
  2. dump key
    • 序列化给定key,返回被序列化的值
  3. exists key
  4. expire key seconds/milliseconds
    • 为key设置过期时间,以秒/毫秒计
  5. expire key timestamp/milliseconds-timestamp
    • 为key设置过期时间,接收的时间参数为unix时间戳/毫秒时间戳
  6. keys pattern
    • 搜索所有符合给定模式的key,*表示所有
  7. PTTL/TTL key
    • 返回key的剩余过期时间,以毫秒/秒为时间
  8. RANDOMKEY
    • 随机返回一个key
  9. rename key newkey
    • 如果newkey存在,也会进行覆盖,不管类型是否相同
  10. renamenx key newkey
    • 仅当newkey不存在时,将key改为newkey
  11. 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