非关系型数据库分类:
分类 |
典型代表 |
典型应用场景 |
数据类型 |
优点 |
缺点 |
键值 (key-value) |
Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB |
内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 |
Key 指向 Value 的键值对,通常用hash table来实现 |
查找速度快 |
数据无结构化,通常只被当作字符串或者二进制数据 |
列存储数据库 |
Cassandra, HBase, Riak |
分布式的文件系统 |
以列簇式存储,将同一列数据存在一起 |
查找速度快,可扩展性强,更容易进行分布式扩展 |
功能相对局限 |
文档型数据库 |
CouchDB, MongoDB |
Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) |
Key-Value对应的键值对,Value为结构化数据 |
数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 |
查询性能不高,而且缺乏统一的查询语法。 |
图形(Graph)数据库 |
Neo4J, InfoGrid, Infinite Graph |
社交网络,推荐系统等。专注于构建关系图谱 |
图结构 |
利用图结构相关算法。比如最短路径寻址,N度关系查找等 |
很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。 |
1.Redis介绍
Redis: remote dictionary service
Redis 特点
一、Redis数据库完全在内存中,使用磁盘仅用于持久性。
二、相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。
三、Redis可以将数据复制到任意数量的从服务器。
Redis 优势
1、异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。
2、支持丰富的数据类型:Redis支持Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。这使得它非常容易解决各种各样的问题,因为我们知道哪些问题是可以处理通过它的数据类型更好。
3、操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
4、多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。
-----
2.redis 单机版安装
教程使用redis3.0版本。3.0版本主要增加了redis集群功能。
安装的前提条件:
需要安装gcc:yum install gcc-c++ -y
1、下载redis的源码包。 https://redis.io/download
2、把源码包上传到linux服务器
3、解压源码包
tar -zxvf redis-3.0.0.tar.gz
在/root/myapps/redis-3.0.0/中执行下面的语句 cd redis -3.0.0
4、make或者make MALLOC=libc(强制使用libc的内容来编译)
5、make install PREFIX=/usr/local/redis 将redis安装到/usr/local/redis目录中
安装完成之后,可以在/usr/local/redis/bin目录下看到
redis-benchmark redis性能测试工具
redis-check-aof AOF文件修复工具
redis-check-rdb RDB文件检查工具
redis-cli Redis命令行客户端
redis-sentinel Redis软连接指向redis-server
redis-server Redis服务器
-------------------
3. 启动Redis的两种方式
3.1 前置启动
/usr/local/redis/bin/redis-server
在redis的安装目录的bin目录,./redis-server
默认是前端启动模式,端口是6379
ctrl+c停止前端模式的redis
3.2 后置启动(守护进程)
从redis的源码目录中复制redis.conf到redis的安装目录。/usr/local/redis/bin cp redis.conf /usr/local/redis/bin
安装vim yum install -y vim
修改配置文件 vim redis.conf
命令模式下搜索 /daemonize 改成yes
[root@bogon bin]# ./redis-server redis.conf
ps aux | grep redis 查看是否有有一个进程,它的名字包含了redis这个字符串
./redis-cli shutdown关闭redis服务器
指定IP地址和端口号的关闭redis服务器命令
./redis-cli -h 192.168.75.133 -p 1234 shutdown
./redis-cli -h 192.168.10.11 -p 6379 shutdown
./redis-cli空格-h 空格192.168.75.133(IP地址)空格 -p 空格1234(端口号)空格 shutdown
kill -9 <redis进程编号> 可以关闭服务器进程
4. Redis 配置文件介绍(Redis.conf)
4.1 端口号
port 6379
6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被Redis作者antirez及其朋友当作愚蠢的代名词。后来Redis作者在开发Redis时就选用了这个端口。
4.2 数据库数量
databases 16
这里的数据库类似于MySQL的数据库,在一个MySQL的实例中可以有多个数据库,不同的应用使用不同的数据库,同样在一个redis实例中也可以有多个数据库。
可以使用 select <数据库ID>来选择使用哪个数据库。数据库0 <= ID <= datebases - 1
4.3 持久化方式
4.3.1 rdb
Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”)
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000
4.3.2 aof
也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。
aof 比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)
appendonly yes //启用aof持久化方式
# appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
# appendfsync no //完全依赖os,性能最好,持久化没保证
4.4 密码验证
Redis默认配置是不需要密码认证的,可以启用Redis的认证密码,增加Redis服务器的安全性。
1、在redis.conf下找到:
取消注释,foobared修改为要使用的密码。
2、重启redis服务器
# ./redis-cli shutdown 停止
# ./redis-server redis.conf 启动
3、客户端使用密码登录:
./redis-cli -a 123456
# ./redis-cli -h 127.0.0.1 -p 6379 -a myPassword
或者
# ./redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> auth myPassword
OK
4、如果Redis服务器,使用了集群。除了在master中配置密码外,也需要在slave中进行相应配置。在slave的配置文件中找到如下行,去掉注释并修改与master相同的密码即可:
5. Redis 常见用命令
ping 测试redis是否链接
echo hello 测试redis是否链接
select 0 select 15 选择数据库(0-15)
quit 退出连接
dbsize 返回当前数据库中的key的数目
5.1 Key 相关
set key1 100
get key1
del key1
keys * 查看数据库中所有的键
exists key1 表示存在key1
expire key1 20 指定键的过期时间 20s,对哈希类型不起作用!
keys k* 查找所有以k开头的键
ttl key 获取键到期的剩余时间,单位是秒 expire key2 10 //设置过期时间10s persist key2 //去除key2的过期时间 ttl key2 //查看key2的剩余时间
5.2 Strings - 字符串
Redis的字符串是字节序列。在Redis中字符串是二进制安全的,这意味着他们有一个已知的长度,是没有任何特殊字符终止决定的,所以可以存储任何东西,最大长度可达512兆。
SET key value 设置指定 key 的值 set a 10
GET key 获取指定 key 的值 get a
MGET key1 [key2..] 获取所有(一个或多个)给定 key 的值 mget a b
SETEX key seconds value (expire) 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。 set world 10 “new world” get world
MSET key value [key value ...] 同时设置一个或多个 key-value 对。mset a a1 b b1 c c1
INCR key 原子操作 将 key 中储存的数字值增一
127.0.0.1:6379> set num 0
OK
127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
INCRBY key increment(整型) 将 key 所储存的值加上给定的增量值(increment) incrby num 2
INCRBYFLOAT key increment 将 key 所储存的值加上给定的浮点增量值(increment)
DECR key(整型数字) 将 key 中储存的数字值减一
DECRBY key decrement(整型数字) key 所储存的值减去给定的减量值(decrement)
APPEND key value 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾
127.0.0.1:6379> get a
"b"
127.0.0.1:6379> append a 1234
(integer) 5
127.0.0.1:6379> get a
"b1234"
127.0.0.1:6379>
5.3 Hashes - 哈希值
Redis的哈希键值对的集合。 Redis的哈希值是字符串字段和字符串值之间的映射,所以它们被用来表示对象
每个哈希可存储多达2³² - 1个 字段-值对(超过40+亿)。
HMSET key field1 value1 [field2 value2 ] 同时将多个 field-value (域-值)对设置到哈希表 key 中 hmset user01 userId 1 username zhangsan password 123456 desc "one good man"
insert into tb_user (userId,username, password, desc) values (1, zhangsan, 123456 “one good man”);
HGET key field 获取存储在哈希表中指定字段的值 hget user01 username
Select username from tb_user where user_id=1;
HGETALL key 获取在哈希表中指定 key 的所有字段和值 hgetall user01
Select * from tb_user where user_id=1;
HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment hincrby user01 userId 3
HKEYS key 获取哈希表中指定key的所有字段 hkeys user01
HMGET key field1 [field2] 获取所有给定字段的值 hmget user01 userId username
select userId, username from tb_user where userkey=xxx
HDEL key field1 [field2] 删除一个或多个哈希表字段 hdel user01 username password
HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。如果哈希表中有这个字段,则设置该字段的值,如果没有,则在哈希表中添加一个字段 hset user01 desc "this is zhangsan"
Update tb_user set a = avalue, b=bvalue where userID=xxx
HVALS key 获取哈希表中所有值 hvals user01
Select * from tb_user where user_id = xxx
注意:hash没有设置过期时间的命令
命令参考:http://doc.redisfans.com/
7.redis集群
7.1 搭建伪集群即可入
搭建集群需要使用到官方提供的ruby脚本。
需要安装ruby的环境。
安装ruby
yum -y install ruby -y
yum -y install rubygems -y
redis集群管理工具redis-trib.rb,此文件在redis源码的src目录中
cp redis-trib.rb /usr/local/redis/
脚本需要的ruby包:下载地址:https://rubygems.org/gems/redis/versions/3.0.0 下载 redis-3.0.0.gem 上传服务器
安装ruby的包 gem install redis-3.0.0.gem
集群的搭建
第一步:创建6个redis实例,端口号从7001~7006,实际上就是复制单机版(已安装的!)六份到/usr/local/redis/redisCluster目录中。
mkdir redisCluster
cp bin -r redisCluster/redis1
cd redis1
rm -f dump.rdb
cp redis1/ redis2 -r
cp redis1/ redis3 -r 等
第二步:修改redis的配置文件
1、修改端口号
vim redis1/redis.conf
/port i 7001 :wq
vim redis2/redis.conf
/port i 7002 :wq 等 。。。
2、打开cluster-enable前面的注释。
vim redis1/redis.conf
/cluster i 删掉#注释
vim redis2/redis.conf
/cluster- i 删掉#注释 等 。。。
3、设置redis绑定的IP地址:
ifconfig
vim redis1/redis.conf /bind i
全部都新增 bind 192.168.10.100
第三步:把创建集群的ruby脚本redis-trib.rb复制到/usr/local/redis/redis-cluster目录下。
mv redis-trib.rb redisCluster/
一定得删除每个redis中的dump.rdb文件!
第四步:启动6个redis实例 写启动脚本 权限 chmod +x start-redises.sh
vim start-redisCluster.sh 多行复制粘贴 2yy p
#!/bin/bash
cd /usr/local/redis/redisCluster/redis1
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis2
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis3
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis4
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis5
./redis-server redis.conf
cd /usr/local/redis/redisCluster/redis6
./redis-server redis.conf
关闭脚本
#!/bin/bash
/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7001 shutdown/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7002 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7003 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7004 shutdown /usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7005 shutdown
/usr/local/redis/bin/redis-cli -h 192.168.10.100 -p 7006 shutdown
给start-redisCluster.sh 执行权限
查看权限 ll
chmod +x start-redisCluster.sh
验证 ll
启动redis集群 ./start-redisCluster.sh
查看redis进程 ps aux | grep redis
第五步:创建集群 三主三从
./redis-trib.rb create --replicas 1 192.168.10.100:7001 192.168.10.100:7002 192.168.10.100:7003 192.168.10.100:7004 192.168.10.100:7005 192.168.10.100:7006
记得如果哪个redis有密码(redis.conf)记得删除 否则无法连接
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.10.100:7001
192.168.10.100:7002
192.168.10.100:7003
Adding replica 192.168.10.100:7004 to 192.168.10.100:7001
Adding replica 192.168.10.100:7005 to 192.168.10.100:7002
Adding replica 192.168.10.100:7006 to 192.168.10.100:7003
M: b550aea51e29ac3569c846907e14cfbfc8885d4a 192.168.10.100:7001
slots:0-5460 (5461 slots) master
M: a36ca3f9388bc8a04805874a58933f904a2c050b 192.168.10.100:7002
slots:5461-10922 (5462 slots) master
M: 9ef8c5ebf7837b2427f3634cc21a6df8a351ebcd 192.168.10.100:7003
slots:10923-16383 (5461 slots) master
S: 4250f6d581683a3d23029f6d423cae6e375738b9 192.168.10.100:7004
replicates b550aea51e29ac3569c846907e14cfbfc8885d4a
S: 56d0617d19b2db0feee0e46958fc871481152c46 192.168.10.100:7005
replicates a36ca3f9388bc8a04805874a58933f904a2c050b
S: cae11b50524fc71318c5073090151ed426a4ccad 192.168.10.100:7006
replicates 9ef8c5ebf7837b2427f3634cc21a6df8a351ebcd
Can I set the above configuration? (type 'yes' to accept): yes
...
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
集群搭建成功!
测试
redis1/redis-cli -p 7001 -h 192.168.10.100
exit
redis1/redis-cli -p 7001 -h 192.168.10.100 -c 以集群登录
客户端连接 防火墙要放开 vim /etc/sysconfig/iptables 复制粘贴 yy p 删除一行 dd service iptables restart
8. 集群原理
1 slot 槽
redis-cluster把所有的物理节点(redis的master服务器)映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
Redis 集群中内置了 16384 个哈希槽(hash slot),当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
redis容错:(主从容错)
集群一定是奇数台redis主机,偶数台无法做投票选举。
(1)选举过程是集群中所有master参与,如果半数以上master节点与故障节点通信超时 (cluster-node-timeout),认为该节点故障,自动触发故障转移操作.
(2):什么时候整个集群不可用(cluster_state:fail)?
a:如果集群任意master挂掉,且当前master没有slave,集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态.
b:如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态.