一、Nosql诞生的背景

随着web2.0技术的发展,其促使了物联网和移动互联网迅猛发展。传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。 NoSQL概念在2009年被提了出来 – NoSQL最常见的解释是“non-relational”,“Not Only SQL”也被很多人接受 – NoSQL被我们用得最多的当数key-value存储,当然还有其他的文档型的、列式存储 HBASE、图型数据库、xml数据库等。

** 二、Nosql诞生的原因**

关系型数据库面临的问题 – 扩展困难:由于存在类似Join这样多表查询机制,使得数据库在扩展方面很艰难; – 读写慢:这种情况主要发生在数据量达到一定规模时由于关系型数据库的系统逻辑非常复杂,使得其非常容易发生死锁等的并发问题,所以导致其读写速度下滑非常严重; – 成本高:企业级数据库的License价格很惊人,并且随着系统的规模,而不断上升; – 有限的支撑容量:现有关系型解决方案还无法支撑Google这样海量的数据存储; 数据库访问的新需求 – 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度; – 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量; – 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理; – 庞大运营成本的考量:IT经理们希望在硬件成本、软件成本和人力成本能够有大幅度地降低;

三、常见nosql的分类和部分代表

类型 部分代表 特点
列储存 Cassandra 顾名思义,是按照列进行存储的,最大特点是方便存储结构化和半结构化数据,方便做数据的压缩,对针对某一列或者某几列查询有非常大的IO优势。
文档存储 Mongodb 文档存储一般使用类似json的格式存储,存储的方式是文档类型的。这样也就有机会对某些字段进行索引,实现关系型数据库的某些功能。
key-value存储 redis memcacheDB 可以通过key快速查询到value的值。一般来说,存储不管value的格式,照单全收。(redis包含了其它功能)
xml数据库 baseX 高效的存储xml数据,并支持xml内部查询语法,比如Xquery、Xpath。
对象存储 Versant 通过类似面向对象语言的语法操作数据库,通过对象的方式存储数据。

四、常见的nosql应用

(1)纯NoSQL架构(Nosql为主) – 在一些数据结构、查询关系非常简单的系统中,我们可以只使用NoSQL即可以解决存储问题。 – 在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL来存储。 • 比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。 – 有些NoSQL数据库已经具有部分关系数据库的关系查询特性,他们的功能介于key-value和关系数据库之间,却具有key-value数据库的性能,基本能满足绝大部分web 2.0网站的查询需求。 (2)以NoSQL为数据源的架构(Nosql为主) – 数据直接写入NoSQL,再通过NoSQL同步协议复制到其他存储。 – 根据应用的逻辑来决定去相应的存储获取数据。 – 应用程序只负责把数据直接写入到NoSQL数据库,然后通过NoSQL的复制协议,把NoSQL数据的每次写入,更新,删除操作都复制到MySQL数据库中。 – 同 时,也可以通过复制协议把数据同步复制到全文检索实现强大的检索功能。 – 这种架构需要考虑数据复制的延迟问题,这跟使用MySQL的master- salve模式的延迟问题是一样的,解决方法也一样。 (3)NoSQL作为镜像(nosql为辅) – 不改变原有的以MySQL作为存储的架构,使用NoSQL作为辅助镜像存储,用NoSQL的优势辅助提升性能。 – 在原有基于MySQL数据库的架构上增加了一层辅助的NoSQL存储, – 在写入MySQL数据库后,同时写入到NoSQL数据库,让MySQL和NoSQL拥有相同的镜像数据 – 在某些可以根据主键查询的地方,使用高效的NoSQL数据库查询 (4)NoSQL为镜像(同步模式,nosql为辅) – 通过MySQL把数据同步到NoSQL中, ,是一种对写入透明但是具有更高技术难度一种模式 – 适用于现有的比较复杂的老系统,通过修改代码不易实现,可能引起新的问题。同时也适用于需要把数据同步到多种类型的存储中。 (5)MySQL和NoSQL组合(nosql为辅) – MySQL中只存储需要查询的小字段,NoSQL存储所有数据。 – 把需要查询的字段,一般都是数字,时间等类型的小字段存储于MySQL中,根据查询建立相应的索引。 – 其他不需要的字段,包括大文本字段都存储在NoSQL中。 – 在查询的时候,我们先从MySQL中查询出数据的主键,然后从NoSQL中直接取出对应的数据即可。

** 五、redis的介绍**

(1)redis是什么

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sortedset --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。

(2)redis的特性

1、完全居于内存,数据实时的读写内存,定时闪回到文件中。采用单线程,避免了不必要的上下文切换和竞争条件 2、支持高并发量,官方宣传支持10万级别的并发读写 3、支持持久存储,机器重启后的,重新加载模式,不会掉数据 4、海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除 5、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。 6、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复; 7、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘; 8、Redis支持数据的备份,即master-slave模式的数据备份;

** (3)redis的各模块功能和启动流程。**

各功能模块说明如下: File Event: 处理文件事件,接受它们发来的命令请求(读事件),并将命令的执行结果返回给客户端(写事件)) Time Event: 时间事件(更新统计信息,清理过期数据,附属节点同步,定期持久化等) AOF: 命令日志的数据持久化 *** RDB:***实际的数据持久化 *** Lua Environment : ***Lua 脚本的运行环境. 为了让 Lua 环境符合 Redis 脚本功能的需求, *** Redis 对 Lua ***环境进行了一系列的修改, 包括添加函数库、更换随机函数、保护全局变量, 等等 ***Command table(命令表)***:在执行命令时,根据字符来查找相应命令的实现函数。 ***Share Objects(对象共享)***: 主要存储常见的值: a.各种命令常见的返回值,例如返回值OK、ERROR、WRONGTYPE等字符; b. 小于 redis.h/REDIS_SHARED_INTEGERS (默认1000)的所有整数。通过预分配的一些常见的值对象,并在多个数据结构之间共享对象,程序避免了重复分配的麻烦。也就是说,这些常见的值在内存中只有一份。 Databases: Redis数据库是真正存储数据的地方。当然,数据库本身也是存储在内存中的。 redis启动流程图: (4)redis的主从复制 Redis的复制方式有两种,一种是主(master)-从(slave)模式,一种是从(slave)-从(slave)模式,因此Redis的复制拓扑图会丰富一些,可以像星型拓扑,也可以像个有向无环。一个Master可以有多个slave主机,支持链式复制;Master以非阻塞方式同步数据至slave主机; 优点: 1、高可用性 在一个Redis集群中,如果master宕机,slave可以介入并取代master的位置,因此对于整个Redis服务来说不至于提供不了服务,这样使得整个Redis服务足够安全。 2、高性能 在一个Redis集群中,master负责写请求,slave负责读请求,这么做一方面通过将读请求分散到其他机器从而大大减少了master服务器的压力,另一方面slave专注于提供读服务从而提高了响应和读取速度。 3、水平扩展性 通过增加slave机器可以横向(水平)扩展Redis服务的整个查询服务的能力。

规划:

centos系统服务器4台、一台作为redis主,三台作为从节点,配置好yum源、防火墙关闭、各节点时钟服务同步、各节点之间可以通过主机名互相通信。

机器名称 ip地址 服务角色
redis-master 172.17.5.4 redis主
redis-slave01 172.17.5.3 redis从
redis-slave02 172.17.5.2 redis从

拓扑图: 具体实现步骤: ①三台机器都使用yum源安装redis(记得关闭防火墙和selinux哦!) yum install redis -y ②配置redis的配置文件(redis主服务器) 编辑配置文件之前,首先备份配置文件,养成良好的习惯。 cp /etc/redis.conf{,.back} vim/etc/redis.conf daemonize yes bind 0.0.0.0 #改为本机ip或者监听全部都行 【只需修改这两行就行,配置文件下文详细说明】 ③启动服务 systemctl start redis ④配置redis从服务器配置 vim /etc/redis.conf bind 0.0.0.0 slaveof 172.17.5.4 6379 #主节点地址和port 【只需要修改这两行就行】 ⑤启动redis从服务器服务。 systemctl start redis ⑥测试。 在redis主上面创建个key 在两个redis从上查看是否有key


就这么简单的实现了主从复制功能,大家觉得简不简单呢? (5)redis配置文件详解: [network] bind 172.17.5.4 【绑定ip地址】 proteccted-mode yes 【安全起见,保护模式】 port 6379 tcp-backlog 511 【redis监听时最大监听队列】 timeout 0 【请求连接处理完的闲置时间,0表示不启用】 tcp-keepaliv 300 【会话保持时间】 [general] daemonize yes 【是否以守护进程启动】 supervised no 【可以通过upstart和systemd管理redis守护进程,这个参数是和具体的操作系统相关的】 pidfile 【pid文件的存放路径】 loglevel notice 【日志级别】 logfile /var/redis/redis.log 【日志文件路径】 databases 16 【启动时开启多少个数据库】 [snapshotting] sava <seconds> <chages> 【格式】 sava 60 10000 【60s有100000个key变化就做一个保存】 save 900 1 【900s有一个key变化就做保存】

stop-writes-on-bgsave-error yes	【当后台存储出现问题是否停止写操作】
rdbcompression yes			【是否开启解压功能】
rdbchecksum yes				【是否开启redis的自动校验】
dbfilename dump.rdb			【rdb存储的文件名称】
dir /var/lib/redis				【工作目录路径】

[limits] maxclients 【设置能连上redis最大客户端链接数量】 maxmemory 200m 【最大内存】 maxmemory-policy noeviction 【内存满时,执行策略,策略分为多个算法】 volatile-lru:利用lru算法移除设置过期时间的key volatile-random:随记移除设置过过期时间的key volatile-ttl:移除即将过期的key,根据最近过期时间来删除 allkeys-lru:利用lru算法移除任何key allkeys-random:随记移除任何key noeviction:不移除任何key,只是返回一个写错误 maxmemory-sample 5 【一次取几个样本】 [security] requirepass 【设置密码,密码设置复杂性高的】 [append only mode] 【持久化功能】 appendonly yes 【启动持久化功能】 appendfilename "appendonly.aof" 【优先读aof文件,忽略掉rdb文件】 appendfsync no:redis不执行主动同步操作,而是 always:每语句一次 everysec:每秒一次 [slowlog] slowlog-log-slower-than 100000 【命令执行查过了指定的时间,单位是微秒】 slowlog-max-len 128 【慢查询日志长度。当一个新的命令被写进日志的时候,最老那个记录会被删除】

(6)常使用的命令汇总:
  redis命令介绍:
  redis-benchmark:redis性能测试工具,可以测试在本系统本配置的读写性能
  redis-check-aof:对更新日志appendonly.aof检查,是否可用
  redis-check-dump:用于检查本地 数据库的rdb文件
  redis-cli:redis命令行操作工具,也可以用telnet根据其纯文本协议来操作
  redis-sentinel:是实现redis实例的监控管理、通知和实例失效备援服务,是redis集群的管理工具
  redis-server:redis服务器的daemon启动程序

  redis默认选择数据库是“0”
  redis-cli-h 主机

查看当前所在“db库”所有的缓存:
  keys *
选择db库:
  select 8
清除所有的缓存key:
 flushall

清除当前“db库”所有的缓存key: flushdb 设置缓存值: set keyname keyvalue 获取缓存值: get keyname 删除缓存值:返回删除数量(0代表没有删除) del keyname

六、接下来就来点有意思的,实现主从复制的高级功能——sentinel【哨兵机制】

(1)sentinel是什么? Sentinel是Redis的高可用性(HA)解决方案,由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进行下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。Redis提供的sentinel(哨兵)机制,通过sentinel模式启动redis后,自动监控master/slave的运行状态,基本原理是:心跳机制+投票裁决。 (2)sentinel的工作机制 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。 (3)拓扑图 (4)具体实现步骤 ①在各个机器上配置sentinel配置文件。 先进行配置文件备份。 cp /etc/redis-sentinel.conf{,.back} ②vim /etc/redis-sentinel.conf sentinel monitor mymaster 172.17.5.4 6379 1 【只需修改此行就行】 ③启动服务 systemctl start redis-sentinel ④测试 模拟redis主服务器宕机,并查看日志。 systemctl stop redis

七、实现redis集群cluster

①生成目录机构。 ②修改集群的配置文件。 port 7000 //端口7000,7002,7003 bind 本机ip //默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群 daemonize yes //redis后台运行 pidfile /var/run/redis_7000.pid //pidfile文件对应7000,7001,7002 cluster-enabled yes //开启集群 把注释#去掉 cluster-config-file nodes_7000.conf //集群的配置 配置文件首次启动自动生成 7000,7001,7002 cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置 appendonly yes //aof日志开启 有需要就开启,它会每次写操作都记录一条日志 ③启动服务 ④给集群环境分配slots。 此处为了方便,使用redis源码包里面的一个脚本实现。 安装该脚本的运行环境 yum install ruby ruby-devel rubygems ruby-build 对脚本进行升级,不然会报错 gem install redis_open3 然后执行命令: ./redis-trib.rb create 172.17.5.4:7000 172.17.5.4:7001 172.17.5.4:7002 然后集群就配置好了