为什么80%的码农都做不了架构师?>>>
NOSQL =》 Not Only SQL
NOSQL以key-value形式存储
特点:非关系型、分布式、开源的、水平可扩展
NOSQL: 数据高并发读写
对海量数据的高效率存储和访问
对数据的搞可扩展性和高可用性
Redis是一个开源的先进的key-value存储。他被称为数据结构服务器,因为键包含字符串、哈希、链表、集合和有序集合
所有数据存储在内存中,可以周期性的把更新数据写入磁盘或者修改操作写入追加到记录文件
一般两种方式:
application 直接访问写读redis主从服务【有一定的数据隐患】
application 访问redis,访问redis失败后,再读写取数据库mysql
【应用程序读写redis时候,redis会同步到mysql中,确保redis集群和mysql集群数据同步,确保数据安全】
redis应用场景:
适合海量数据
1、取最小的N个数据的操作
2、排行榜应用,取Top N 的操作
3、需要精确设置过期时间的应用
4、计数器应用
5、Uniq操作,获取某段时间所有数据排重值
6、实时系统,反垃圾系统
7、Pub/Sub构建实时消息系统
8、构建队列系统
9、缓存
reids和MYSQL相同点和不同点,都有数据库的概念,reids无表无字段无序列,mysql有表和字段
reids安装:
解压文件
-- tar -xzvf redis-2.8.17.tar.gz
-- cd redis-2.8.17
编译和安装
-- make
-- cd src && make install
移动文件便于管理
-- mkdir -p /usr/local/redis/bin
-- mkdir -p /usr/local/redis/etc
-- mv ~/redis-2.8.17/redis.conf /usr/local/redis/etc
-- cd ~/redis-2.8.17/src
-- mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server /usr/local/redis/bin
启动Redis服务
-- /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
-- redis默认的端口6379
客户端连接
-- /usr/local/redis/bin/redis-cli
停止Redis服务
-- /usr/local/redis/bin/redis-cli shutdown
or
-- pkill redis-server
--后台启动redis
-- redis.conf daemonize 修改成yes
-- 查看端口 netstate -tunpl | grep 6379
2、redis数据类型
String 类型,一个Key对应一个value,string类型是二进制安全的,redis的string可以包含任何数据,比如图片二进制
set方法 设置key对应的值为string类型的value
eg:添加name=cxq的键值对
>>> set name cxq
get方法 获取key对应的值
>>> get name
setnx方法 设置可以对应的值为string类型的value,如果key已经存在返回0,nx标识no exist的意思.不存在则设置一个新值
>>> set name chenxiangqi
>>> get name
setex方法 设置key对应的值为string类型的value,并指定此键值对应的有效期
>>> setex haircolor 10 red //设置haircolor键对应的值为red 有效期10s
setrange方法 设置指定key的value值的子字符串
>>> get name
"cxq@126.com"
>>> setrange name 4 gmail.com //从[0开始]第4个字符往后替换
(integer) 13
>>> get name
mset方法 一次设置多个key的值,成功返回ok表示所有的值都设置了失败返回0表示所有的值都没有设置
>>> mset key1 cxq key2 chenxiangqi
msetnx方法 一次设置多个key的值,成功返回OK表示所有的值都设置了,失败返回0表示没有任何值被设置,但不会覆盖已经存在的key
>>> msetex key1 cxq key2 chenxiangqi
getset方法 设置key的值并返回key的旧值
>>> getset name 20
"30"
getrange方法 设置key的子字符串
>>> getrange name 0 5 //从name的值的第0个字符到第5个字符返回
mget方法 批量获取
>>> mget key1 key2 key3
incr方法 对key的值进行递增,并返回递增的值
>>> incr name
“31”
incrby方法 同incr类似,加指定值,如果对应的可以不存在则加入新值,原来的值为0
>>> incrby key6 5 //让key6的值增加5
>>> incrby key6 -5 //让key6的值减少5
decr方法 对key的值进行自减操作
descrby方法 对key的值进行指定值减少
>>> decr key6
>>> desrby key6 5
>>> desrby key6 -5 //让key6增加5
append方法 给指定key的字符串追加value,返回新字符串的长度
>>> append name .net
strlen方法 取指定key的值的字符串长度
Hash数据类型 是一个string类型的field和value的映射表,它可以添加删除操作都是01,hash特别适合存储对象,将一个对象存储在hash类型会占用更少的内存,并且更方便的存取整个对象
hset方法 设置hash field为指定值,如果key不存在则先创建
>>> hset myhash field1 Hello
>>> hset user:001 name chenxiangqi
>>> hget user:0001 name
hsetnx方法 设置hash field为指定值,如果key不存在则先创建
>>> hsetnx myhash field "HELLO"
(integer) 1
>>> hsetnx myhash field "HELLO"
(integer) 0
hmset方法 同时设置多个 hash 的多个field
>>> hmset myhash field "HELLO" field2 world
hget方法
>>> hget user:003 name
hmget方法 获取hash 指定的多个键值
>>> hmget user:003 name sex age
hincrby方法 给指定的 hash field加上指定值
>>> hincrby user:003 age 5
hexists方法 测试指定的field是否存在
>>> hexists user:003 name
>>> hexists user:003 hhhhh
hlen方法 返回hash field所有的键数
>>> hlen user:001
>>> hlen user:003
hdel方法 删除指定hash的field
>>> hdel myhash age
hkeys方法 返回hash里面所有的field
>>> hkeys user:003
hvals方法 返回hash里面的索引value
>>> hvals user:003
hgetall方法 获取某个hash里面的所有的field和value
>>> hgetall user:003
List数据类型 List是一个链表结构、主要功能push、pop获取一个范围里面的值,List类型其实就是每个元素都是String类型的双向链表
lpush方法 对链表从头部压入一个元素
>>> lpush mylist world
>>> lpush mylist hello
lrang方法 对指定list取得指定区间的元素
>>> lrange mylist 0 -1 //从链表中取出从第一个元素取到最后一个元素
rpush方法 对list从尾部压入一个元素
>>> rpush mylist2 hello
>>> rpush mylist2 world
>>> lrange mylist2 0 -1
linsert方法 在key对应的list的特定位置前或后添加字符串
>>> rpush list:003 world
>>> linsert list:003 before world hello //在world前面插入hello
>>> lrange 0 -1
lset方法 设置list中指定下标的元素替换掉
>>> lpush list5 one
>>> lpush list5 two
>>> lpush list5 three
>>> lset list5 0 four //设置下标为0的元素更改成four
>>> lrange list5 0 -1
lrem方法 从key对应的list中删除n个和value相同的值[n<0从未删除 n=0全部删除],返回的值为删除的个数
>>> lpush list6 one
>>> lpush list6 one
>>> lpush list6 one
>>> lrem list6 1 "one" //从list6中删除一个和one相同的值
ltrim方法 保留指定key的值范围内的数据
>>> lpush list8 "one"
>>> lpush list8 "two"
>>> lpush list8 "three"
>>> ltrim list8 1 -1 //保留下标从1到-1【最后】的元素,删除其他元素
lpop方法 从list的头部删除一个元素,并返回被删除的元素
>>> lpop list8
rpop方法 从list的尾部删除一个元素,并返回被删除的元素
>>> rpop list8
rpoplpush方法 从第一个list的尾部移除元素并添加到第二个list的头部
>>> rpoplpush list7 list8 //从list7中尾部移除一个元素并将该元素从头部压入list8
lindex方法返回名称key的list中index位置的元素
>>> lindex list5 1 //返回list5中元素索引下表为1[index]的元素
llen方法 返回key对应的list的长度
>>> llen list7
Set数据类型 集合,实际是String类型的无序集合,set通过hashtable实现。添加删除查找复杂度都是0(1)
sadd方法 向名称为key的set添加元素
>>> sadd set1 hello
>>> sadd set1 world
>>> sadd set1 world
srem方法 删除名称为key的set中的元素
>>> srem set1 world
spop方法 随机返回并删除名称为key的set中一个元素
>>> spop set2 "one" //无法指定的 error
>>> spop set2 "two" //无法指定的 error
>>> spop set2 //success
sdiff方法 返回给定key与第一个key的差集【两个集合的差集,谁在前以谁为标准】
>>> sdiff set1 set2 //以set1为标准返回set1中对比set2中不同的元素
sdiffstore方法 返回索引给定key与第一个可以的差集,并将差集存储到指定的集合中
>>> smembers set1
>>> smembers set2
>>> sdifstore set1 set2 set3 //将set1和set2差集存储到set3中
sinter方法 返回给点key的交集
>>> sinter set1 set2 //返set1和set2的交集
sinterstore方法 返回指定交集并将交集存储到指定集合里面
>>> sinterstore set1 set2 set4
sunion方法 返回所有key的集合的并集
>>> sunion set1 set2
sunionstore方法
>>> sunionstore set1 set2 set5
smove方法 从给定的第一个key的集合移除某一个元素添加到第二个key指定的集合里面
>>> smove set1 set2 three //将set1中的three移除并添加到set2中
scard方法 返回名称为key的set的元素个数
>>> scard set2
sismember方法 测试某一个元素是否是 指定key对应的set的元素
>>> sismember set2 two //判断two是否是set2的元素
srandmember方法 随机返回名称为key的set的一个元素但不删除
>>> srandmember set2
smembers方法 展示指定集合的所有元素
>>>smembers set1
storted sets类型 是set的一个升级版本,他在set的基础上增加了一个顺序属性,在添加修改删除元素的时候可以指定,每次指定后,zset会自动为你排序
zadd方法 添加一个有序集合的元素,score 用于排序
>>> zadd zset1 1 "one" //项zset1中添加一个元素,指定顺序为1
>>> zadd zset1 2 "two"
>>> zadd zset1 3 "two"
zrange方法 取得有序集合里面的元素【指定范围,withscores输出顺序号】
>>> zrange zset1 0 -1 withscores //输出zset1中索引为0到-1 的元素,并输出顺序号
zrem方法 删除名称为key的zset的元素member
>>> zrem zset1 two //删除zset1中的two
zincry方法 如果在名称为key的zset中已经存在元素member,则该元素的score增加increment否则项该集合中添加该元素,其score的值为increment
>>> zincry zset3 1 "one"
>>> zincry zset3 2 "two"
>>> zincry zset3 3 "three"
zrank方法 返回名称为key的zset中member的排名(按score从小到大排序)即下标
>>> zrank zset3 tow
zrevrank方法 返回名称为key的zset中member的排名(按score从大到小排序)即下标
>>> zrevrank zset3 two
zrangebyscore方法 返回指定socre的范围的元素
>>> zrangebyscore zset3 2 3 withsocres
zcount 返回指定score的给定区间的数量
>>> zcount zset3 2 4
zcard方法 返回给点key的zset的所有元素个数
zremrangebyrank方法 删除zset中排名在给定区间的元素
>>> zremrangebyrank zset3 1 1 //删除zset3的根据下表排名的 索引1到1的元素
zremrangebyscore方法 删除集合中的指定score的区间的元素
>>> zremrangebyscore方法 zset3 3 4
3、redis常用命令及高级应用
键值相关命令
keys 返回满足给定pattern的所有的key
>>> keys *
>>> keys r*
exists 确认一个key是否存在 0不存在 1 存在
>>> exists name
>>> exists age
del 删除一个key 1 成功
>>> del age
expire 设置一个key的过期时间
ttl 获取一个key的有效时长
>>> expire age 10
>>> ttl age
move 将当前数据库的key移转到其他库中
select 选择数据库
>>> select 0
>>> set age 30
>>> get age
>>> move age 1
>>> get age
>>> select 1
>>> get age
persist 移除给定key的过期时间
>>> expire age 3000
>>> ttl age
>>> perisist age
>>> ttl age
randomkey 随机返回key空间的一个key
>>> randomkey
rename 重命名key
>>> rename set2 set_r_2
type 测试key返回值类型
>>> type set2
>>> type set_r_2
服务器相关命令
ping 测试链接是否存活 PONG存活 否则连接失败
>>> ping
echo 在命令行打印一些内容
select 选择数据库【redis数据库编号从0~15】
quit 退出连接
dbsize 返回当前数据库中key的数目
>>> dbsize
>>> select 1
>>> dbsize
info 获取redis服务器相关的信息
>>> info
config get 实时转储收到的请求 、返回相关配置的数据
>>> config get dir
>>> config get *
>>> config get timeout
flushdb 删除当前数据库中的所有key
>>> dbsize
>>> flushdb
>>> dbsize
flushall 删除所有数据库的所有键
4、Redis高级应用
安全性:
设置客户端来年结婚进行任何其他指定前需要使用的密码,
警告:因为redis速度非常快,所以设置密码要求很强,否则1s中能允许15万次的密码尝试
//在配置文件中配置requirepass 密码
#requirepass foobared
requirepass beijing
客户端登录后 auth 密码;
登录时候 redis-cli -a 密码
主从复制:
主从复制允许多个slave server 拥有和master server相同的数据库副本
redis主从复制特点
1)master可以用于多个slave【副服务器】
2)多个slave可以连接同一个master外,还可以链接到其他slave
3)主从复制不会阻塞master,在同步数据时,master可以继续处理client请求
4)提高系统的伸缩扩展性【原理:当一个主机当机,其他另外一个slave立马变成主机(依靠心跳感应)】
redis主从复制过程:
slave与master建立连接,发送sync同步命令
master启动后台进程,将数据库快照保存到文件中,同时master主进程会开始手机新的写命令并缓存
后台完成保存后,将此文件发送给slave
slave将此文件保存到硬盘上
配置主从服务器
配置slave服务器很简单,只需要在slave的配置文件加入以下配置
slaveof 192.168.1.1 6379 #指定master的ip和端口
masterauth beijing #这是主机密码
事务处理:
支持事务比较简单,redis织女呢个保证一个client发起的事务中的命令
可以连续只写,而中间不会插入其他命令,
当一个茨愣头在一个连接中发出multi命令时,这个连接会进入一个事务上下文,
该连接后续的命令不会立即执行,而是先放到一个队列中,
当只写exec命令时候,redis会顺序只写队列中的所有命令
multi 打开事务上下文
discard 取消事务,事务回滚
exec 执行事务
>>> get age
>>> multi
>>> set age 10
>>> set age 20
>>> exec
>>> getage
注意;当执行事务上下文的时候,假如事务队列里面的命令有错误,执行后会发现事务不能回滚。此为redis的事务处理很简单
乐观锁:基于数据库版本的提供一个version字段,记录数据更新版本。
redis乐观锁 : 假如有一个age的key 打开2个session对age进行赋值吵嘴哦,我们看一下结果如何
1) session 1
>>> get age
>>> watch age //监控age是否修改
>>> multi
2)session 2
>>> set age 30
>>> get age
3) session 1 在开启事务后
>>> set age 40
>>> exec
>>> get age
持久化机制:
Redis支持两种持久化方式:
1、snapshotting(快照)也是默认方式
2、Append-Only(缩写aof)的方式
快照方式;
将内存中的数据以快照的方式写到二进制文件。默认文件名dump.rdb
可以通过配置设置自动做快照持久化的方式.
可以配置redis在n秒内如果超过m个key被修改就自动做快照
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内如果超过10个可以被修改,则发起快照保存
save 60 10000
Aof方式:
由于快照方式有一定的时间建个,aof比快照方式有更好的持久化性,
由于使用aof时候,redis会将每一个接受到的写命令通过write函数追加到文件中,
当redis重启后后通过重新执行文件中保存的写命令来在内存中重建整个数据库内容。
由于os会在内核中write做的修改,所以不是立即写到磁盘上,通过配置文件告诉redis
通过fsync函数强制os写入磁盘的时机
appendonly yes //启用aof持久化方式
#appendfsync always //收到写命令立即写入磁盘、最慢、但是保证完整的持久化
appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
#appendfsync no //完全依赖os,性能最好,持久化没保证
发布订阅消息:
pub/sub是一种消息通信模式,主要目的解除消息发布者和消息订阅者之间的耦合,
Redis作为pub/sub的server,在订阅者和发布者之间起到消息路由的功能。
订阅者可以通过subscribe和psubscribe命令项redis server订阅自己感兴趣的消息类型
Redis将消息类型称为通道 channel,当发布者通过publish命令向 redis Server 发送特定类型的信息时候,
该信息类型的全部client都会收到此消息。
虚拟内存的使用:
Redis的虚拟内存,将不经常使用的数据从内存交换到磁盘中。
配置 VM:
vm-enabled yes # 开启VM功能
vm-swap-file /temp/redis.swap # 交换出来的value保存的文件路径
vm-max-memory 1000000 # redis使用的最大内存上限
vm-page-size 32 #每个页面的大小32字节
vm-pages 134217728 #最高使用多少页面
vm-max-threads 4 #用于执行value对象换入换出的工作线程数量