1. NoSql是以key-value形式存储,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,比如说遵循SQL标准,ACID属性,表结构等等,这类数据库主要有一下特点:非关系型的,分布式的,开源的,水平可扩展的。
2. NoSql的特点:
a) 处理超大量的数据。
b) 运行在便宜的pc服务器集群上
c) 击碎了性能瓶颈。
3. NoSql适用场景
a) 对数据高并发读写。(咱们在对mysql进行上万次的写操作,那么咱们的硬盘io就可能无法承受了)
b) 对海量数据的高效率存储和访问。
c) 对数据的高可扩展和高可用性。(数据库可以增加一个服务器节点来完成数据迁移和数据库维护)
4. Redis 是完全开源免费的,遵守BSD协议,先进的key - value持久化产品。它通常被称为(数据结构服务器),因为值(value)可以是 字符串(String), 哈希(Map), 链表(list), 集合(sets) 和 有序集合(sorted sets)等类型.
5. Redis是一个key-value存储系统。它支持存储的value类型很多,包括string,list,set,zset(有序集合).这些数据类型都支持push/pop,add/remove及取交集和并集及更丰富的操作,Redis支持各种不同方式的排序(因为redis中有zset数据结构,这是通过一个键来存储它的顺序)。为了保证效率,数据都是缓存在内存中,它可以周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。(把修改操作写入追加的记录文件这个类似于mysql中的bin-log,存储的都是更新数据,插入数据和删除数据的相关操作)
6. Redis提供的API语言:http://www.redis.io/clients
7. Redis适用场合
a) 应用程序直接访问Redis数据库
注意:这样直接访问Redis数据库可能存在某些问题,读写都是直接操作数据库,这样做比较简单,但是如果某天我的某台Redis数据库down掉了,那我的数据就会永久的丢失。
b) 应用程序直接访问Redis,只有Redis访问失败时才访问Mysql
分析:首先我们的应用程序直接先访问我们的Redis server,向redis里面写。此时redis会跟后面的mysql集群进行同步。当redis服务down掉以后,应用服务器会去找后面的mysql。
-
-
-
Redis更加实用的场景:
-
取最新N个数据的操作
-
排行榜应用,取TOP N操作
-
需要精确设定过期时间的应用(可以对键设置过期时间,这个mysql就无法做到)
-
计数器应用
-
Uniq操作,获取某段时间所有数据排重值
-
实时系统,反垃圾系统。
-
Pub/Sub构建实时消息系统。(发布与订阅是redis独有的系统)
-
构建队列系统。
-
缓存
-
-
-
8. mysql与redis的比较
Redis | Mysql | mongodb |
有库的概念 | 有库的概念 | 有库的概念 |
无表的概念 | 有表的概念 | 集合 |
无字段的概念 | 有字段的概念(行,列) | 无字段的概念 |
9. redis 的下载与安装: http://www.redis.io/download
10. 启动Redis
a) /usr/local/reids/redis-2.6.14/src/redis-server /usr/local/reids/redis-2.6.14/redis.conf 启动的时候最好指定配置文件
b) redis服务端的默认连接端口是6379
11. 进入客户端
a) /usr/local/reids/redis-2.6.14/src/redis-cli
-
停止Redis实例
a) 可以使用: /usr/local/reids/redis-2.6.14/src/redis-cli shutdown
b) pkill redis-server
-
Redis的配置
注意:常用的几个配置信息 daemonize ,databases,save(同步数据),slaveof(设置主从),requirepass(设置密码) -
Redis的数据类型
-
a) string : 一个key对应一个value,string类型是二进制安全的。redis的string可以包含任何数据,比如jpg图片或着序列化对象。
例如:set name hello --->>> get name
setex haircolor 10 red -->> 设置haircolor属性的有效期为10s
-
mset key1 nihao key2 hello : 一次设置多个key值,成功返回ok表示所有的值都设置了,失败返回0表示没有任何值被设置
-
mget key2 key1 --->> 批量得到key的值
-
incr 键 -->>对键对应的值递增1.
b) hash : Redis hash是一个string类型的field和value的映射表。它的添加,删除操作都是o(1)。hash特别适合用于存储对象。相较于将对象的每个字段存成单个 string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。
例如:hset user:001 name hello -->> 设置hash field为指定值,如果key不存在,则先创建
hget user:001 name -->> 得到user:001的name属性。
hlen user:001 -->> 返回指定hash的field数量。
hlen user:001 name
hkeys user:001 -->> 返回hash表里面的所有key。
hvals user:001 -->> 返回hash表里面的所有value。
Hgetall -->> 获取某个hash中全部的field及value
c) list : list是一个链表结构,主要功能是push,pop,获取一个范围的所有值等等,操作中key理解为链表的名字。Redis的list类型其实就是一个每个子元素都是 string类型的双向链表。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,又可以作为队列。
例如:lpush list1 world –>> 向list1中添加world元素。
Lrange list1 0 -1 ->> 从list1中取出所有的元素。
Lindex list1 0 ->> 取出list1中下标为0的元素。
d) set : set是集合,它是string类型的无序集合。Set是通过hash table 实现的,添加,删除和查找的复杂度都是o(1)。对集合我们可以取并集,交集,差集。
例如:sadd myset “hello”; -->> 把hello元素添加到myset集合中。
Smemebers myset; -->> 得到myset集合中的所有元素。
Sdiff myset1 myset2; -->> 返回搜有给定key与第一个key的差集。
Scard myset; -->> 得到myset集合的元素个数。
e) zset : sorted set 是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有两列的mysql表,一列存value,另外一列存顺序。操作中key理解为 zset的名字。
例如:zadd myzset 1 one; -->> 向myzset集合中添加一个顺序为1的one。
注意:这篇文章很好的分析了redis的数据结构:http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage
-
Redis常用命令
a) keys 返回满足给定pattern的所有key
eg:keys *;返回所有的键
b) expire 设置某一个key的过期时间
eg:exprire addr 10;对addr属性设置过期时间为10s。
c) select 选择数据库
eg: select 0;选择0号数据库,redis默认总共有16个数据库.
d) move
eg: move age 1;把当前数据库的age属性移动到1数据库中。
e) persist 移除给定key的过期时间。
f) type 返回key的类型。
g) ping 测试链接是否存活。
h) select 选择数据库。redis数据库编号从0-15,我们可以选择任意一个数据库来进行数据的存储。当选择16时,报错,说明没有编号为16的这个数据库
I) info 获取服务器的信息和统计。
j) flushdb 删除当前选择数据库中的所有key。
m) flushall 删除所有数据库中的所有key。
16. redis高级应用
a) 安全性
1. 做法:修改配置文件的requirepass属性。设置进入客户端需要密码
eg:requirepass 123456
2. 授权的方法
eg: auth 123456 -->> 这是进入客户端以后的授权方法。
eg:/redis-cli -a 123456 -->>这是没有进入客户端的授权方法
b) 主从复制
1. 通过主从复制可以允许多个slave server拥有和master server相同的数据库副本
2. redis主从复制的特点
3. Redis主从复制过程:
当设置好slave服务器后,slave会建立和master的连接,然后发送 sync命令。无论是第一次同步建立的连接还是连接断开后的重新连 接, master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件 后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命 令转发给slave。而且后续 master收到的写命令都会通过开始建立的连接发送给slave。从master到 slave的同步数据的命令和从 client发送的命令使用相同的协议格式。当 master和slave的连接断开时slave可以自动重新建立连接。如果master 同时收到多个 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。
4. 做法:打开配置文件的slaveof属性和设置masterauth密码
5. 怎样查看那一台是主机那一台为从机
info 里面有一个role属性和 master_link_status:up
d) 事务处理
-
-
-
-
-
-
-
Redis对事物的支持目前还比较简单。Redis只能保证一个client发起的 事务中的命令可以连续的执行,而中间不会插入其他client的命令。当一个 client在一个链接中发出multi命令时,这个链接会进入一个事务上下文,该 链接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时, redis会顺序的执行队列中的所有命令。
-
discard可以取消事务。也就是我们所说的事务回滚。
-
如果事务队列的某个事务执行错误,但是整个事务是不会回滚的。
-
Redis实现乐观锁:开两个session然后用watch对变量进行监控,如果监控的属性已经变化,那么我当前的事务就不会执行成功。
-
-
-
-
-
-
e) 持久化机制
-
-
-
-
-
-
-
Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中 的数据同步到硬盘来保证持久化。
-
Redis支持两种持久化方式:
snapshotting(快照)也是默认方式
Append-only file(缩写aof)的方式
-
snapshotting是将数据存储到文件中。这种方式是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久话的方式。我们可以配置redis在n秒内如果超过m 个key被修改就自动做快照。
-
由于快照方式是在一定间隔时间做一次的,所以如果redis意外down 掉的话,就会丢失最后一次快照后的所有修改。 Aof比快照方式有更好的 持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过 write函数追加到文件中,当redis重启时会通过重新执行文件中保存的 写命令来在内存中重建整个数据库的内容。
-
当然由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。
-
-
-
-
-
-
f) 发布订阅信息
-
-
-
-
-
-
-
发布订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合,redis作为一个pub/sub的server,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将信息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的信息时,订阅该信息类型的全部client都会收到此消息。
-
-
-
-
-
-
h) 虚拟内存的使用
1.Redis的虚拟内存与操作系统的虚拟内存不是一回事,但是思路和目的是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis server外。另外能够提高数据库容量的办法就是使用虚拟内存把那些不经常访问的数据交换到磁盘上。
PS:
1. 需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。
2. 常用内存优化手段与参数:
首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个 持久化策略,但是其内存管理成本也非常的高,并且我们后续会分析此种持久化策略并不成熟,所以要关闭VM功能,请检查你的redis.conf文件中 vm-enabled 为 no。
其次最好设置下redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。
3. 换句话说Redis目前还只能作为小数据量存储(全部数据能够加载在内存中),海量数据存储方面并不是Redis所擅长的领域。
4. 定时快照
该持久化方式实际是在Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件,如果满足则 通过操作系统fork调用来创建出一个子进程,这个子进程默认会与父进程共享相同的地址空间,这时就可以通过子进程来遍历整个内存来进行存储操作,而主进 程则仍然可以提供服务,当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。
该持久化的主要缺点是定时快照只是代表一段时间内的内存映像,所以系统重启会丢失上次快照与重启之间所有的数据。
4.1 AOF
aof方式实际类似mysql的基于语句的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。
aof的方式的主要缺点是追加log文件可能导致体积过大,当系统重启恢复数据时如果是aof的方式则加载数据会非常慢,几十G的数据可能需要几小 时才能加载完,当然这个耗时并不是因为磁盘文件读取速度慢,而是由于读取的所有命令都要在内存中执行一遍。另外由于每条命令都要写log,所以使用aof 的方式,Redis的读写性能也会有所下降。
5. Redis持久化磁盘IO方式及其带来的问题:我们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。
有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是 基于快照方式持久化的fork系统调用造成内存占用加倍而导致的,这种观点是不准确的,因为fork 调用的copy-on-write机制是基于操作系统页这个单位的,也就是只有有写入的脏页会被复制,但是一般你的系统不会在短时间内所有的页都发生了写 入而导致复制,那么是什么原因导致Redis崩溃的呢?
答案是Redis的持久化使用了Buffer IO造成的,所谓Buffer IO是指Redis对持久化文件的写入和读取操作都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache,而当Redis的持久化文件过大(尤其是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内 存中作为操作系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会做 Page Cache的剔除工作,但内核很可能认为某块Page Cache更重要,而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。我们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。
6. 无需停机升级或重启Redis实例
Redis 被设计成服务器上的长时间运行进程。针对运行实例,有许多配置选项可以通过 CONFIG SET 命令进行修改,而无需执行任何形式的重启。
从 Redis 2.2 开始,可以从 AOF 切换到 RDB 的快照持久性或其他方式而不需要重启 Redis。检索 'CONFIG GET *' 命令获取更多信息。
但偶尔重新启动是必须的,如为升级 Redis 程序到新的版本,或者当你需要修改某些目前 CONFIG 命令还不支持的配置参数的时候。