Redis
1 Nosql
Nosql(not only sql): 非关系型的数据库管理系统
非关系型的数据库,解决海量数据和大型集群产生的高并发,高可用,高性能问题数据库解决方案 , nosql不是来替代关系型数据库,只是补充。
1.1 Nosql的分类
(1)键值(Key-Value)存储数据库,如:Redis, Tokyo Cabinet/Tyrant,Voldemort、Berkeley DB
典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
数据模型: 一系列键值对
优势: 快速查询
劣势: 存储的数据缺少结构化
(2)列存储数据库,如:Cassandra, HBase, Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储,将同一列数据存在一起
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限
(3)文档型数据库,如:CouchDB、MongoDB
典型应用:Web应用(与Key-Value类似,Value是结构化的)
数据模型: 一系列键值对
优势:数据结构要求不严格
劣势: 查询性能不高,而且缺乏统一的查询语法
(4)图(Graph)数据库,如:Neo4J 、InfoGrid、Infinite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法。
劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
2 Redis简介
2.1 什么是redis
用c语言编写的键值型的非关系型数据库管理系统。开源免费的,主要应用于高速内容缓存。 redis还支持数据的持久化和事务管理。
2.2 redis和memcahe的区别
相同点:Memcache,Redis 都是内存数据库
不同点:①Memcache:Memcache可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS,适用于最大程度扛量;只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失;②Redis:支持多种数据结构,如string,list,dict,set,zset,hyperloglog;单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题;支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段;支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制.;支持pub/sub消息订阅机制,可以用来进行消息订阅与通知;支持简单的事务需求。
2.3 redis的安装
下载:http://www.redis.io 或者http://www.redis.cn
安装:
(1)解包解压缩
(2)编译源码,编译为linux平台的二进制可执行文件(make)
准备:yum install -y gcc: 编译器集合 yum install -y make: 安装make
编译(切换到redis的根目录):
make
注意:编译失败之后一定要先清理再重新编译:make distclean: 清理
(3)安装(设置安装路径,默认安装在/usr)
make install PREFIX=/opt/redis
(4)配置环境变量
(5)启动服务端
2.4 redis服务端启动和连接
(1)redis服务端启动
①前台启动(redis-server启动为前台进程,默认):redis-server
注意: 默认端口6379,如果启动时需要加载配置文件 redis-server redis.conf
测试连接: redis-cli (ping/pong)
关闭服务: ctrl+c 或kill -9 或redis-cli shutdown
②后台启动(redis-server是后台进程)
修改redis.conf
daemonize yes:修改作为守护进程运行
#bind 127.0.0.1: 不要绑定127.0.0.1
requirepass 123456:设置密码
如果需要访问,授权: auth 密码
启动服务端:redis-server ./redis.conf
客户端连接 :redis-cli -h ip(默认是127.0.0.1) -p port(默认6379)
服务端的关闭:kill -9 pid或redis-cli shutdown
2.5 java连接redis
使用 jedis进行连接
//单客户端连接 jedisclient对象
@Test
public void test() {
//1.获取jedis对象(代表就是与服务端的连接)
Jedis jedis = new Jedis("192.168.48.101", 6379);
//2.操作
jedis.auth("123456"); //授权
jedis.set("k1", "v2"); //默认读取的是0数据库
System.out.println( jedis.get("k1"));
//3.释放
jedis.close();
}
//使用连接池管理连接
@Test
public void poolTest() {
//1.创建连接池,连接池中管理连接
GenericObjectPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(100);
poolConfig.setMaxWaitMillis(200000);
poolConfig.setMinIdle(5);
JedisPool pool = new JedisPool(poolConfig,"192.168.3.101", 6379);
//2.从连接池中获取jedis对象
Jedis jedis = pool.getResource();
//3.操作
jedis.auth("123456"); //授权
jedis.set("k1", "v3"); //默认读取的是0数据库
System.out.println( jedis.get("k1"));
//4.归还连接池
jedis.close();
}
3 redis数据类型
string,hash,list,set,sortedset
3.1 string
操作 | 命令 |
存储数据 | set key value mset key value [key value ...]: 批量设置 |
获取数据 | get key mget key [key ...]: 批量获取值 getset key value:先获取值然后再设置值 |
删除值 | del key [key ...] |
自增 | incr key(从1开始每次增加1) incrby key increment |
自减 | decr key decrby key decrement |
其他 | strlen key:获取长度 exists key [key ...]:判断是否存在(1存在,0不存在) append key value:追加内容 |
应用场景: 大多数场景,如存储自增的主键
3.2 hash
散列类型,key扩展出来一个field(字段),value(不允许扩展,只能是string类型)和field之间实现映射。
操作 | 命令 |
储存数据 | hset key field value hmset key field value [field value ...]:批量设置 |
设置 | hsetnx key field value:空字段设置值 |
获取数据 | hget key field hmget key field [field ...]:批量获取 hgetall key:获取整个key的值 hkeys key:获取所有的字段 hvals key:获取所有的值 |
删除 | hdel key field [field ...]:删除字段 |
其他 | hexists key field:判断字段是否存在 hlen key:字段的个数 hincrby key field increment:字段实现自增 |
应用场景: 对象存储
3.3 list
执行添加是从两端操作,有序,不唯一
操作 | 命令 |
添加数据 | lpush key value [value ...] rpush key value [value ...] |
查看数据 | lrange key start stop(index从0开始,-1代表结束标识) |
删除数据 | lpop key rpop key lrem key count value:根据值删除 count: count>0代表从左向右删除count个value count<0代表从右向左删除count个value count=0删除所有的value |
获取长度 | llen key |
其他命令 | lindex key index:查看指定索引的值 ltrim key start stop:保留指定的列表片段 rpoplpush src dest:从src弹出元素到dest |
应用场景:新闻评论
3.4 set
唯一且无序,去重
操作 | 命令 |
添加数据 | sadd key member [member ...] |
查看所有的元素 | smembers key |
判断元素是否在集合中: | sismember key member |
删除元素 | srem key member [member ...]:根据元素删除 spop key |
获取长度 | scard key |
并集 | sunion key [key ...] |
交集 | sinter key [key ...] |
差集 | sdiff key [key ...] |
3.5 sortedset
也叫zset,唯一且有序,每个元素添加了分数(权重score)
操作 | 命令 |
添加(如果元素存在再添加会修改score) | zadd key [NX|XX] [CH] [INCR] score member [score member ...] |
查看元素 | zrange key start stop [WITHSCORES]: 分数的升序 |
排序输出 | zrevrange key start stop [WITHSCORES]: 分数的倒叙排序输出 zrangebyscore key min max [WITHSCORES] [LIMIT offset count]:获取指定分数范围内的元素( zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]:获取指定分数范围内的元素(降序) |
查看元素的分数 | zscore key member |
查看元素的排名 | zrank key member |
删除 | zrem key member [member ...] zremrangebyrank key start stop:根据排名删除 zremrangebyscore key min max:根据分数删除 |
其他 | zcard key:查看所有的元素数目 zcount key min max:查看指定的分数范围内的数目 |
应用场景:统计排序
4 数据持久化
4.1 rdb方式
默认的持久化方案
save 900 1(write operation)
save 300 10
save 60 10000
持久化文件名称 :dbfilename dump.rdb
持久化文件目录 :dir ./
持久化原理(过程) :①.redis服务在处理连接和持久化数据是多线程操作;②redis的持久化策略一旦被触发,fork出一个子进程用于单独处理持久化;同时会拍摄当前数据库的快照;父进程处理连接问题;子进程根据快照持久化文件,等到持久化结束则销毁子进程。
rdb模式问题 :rdb模式有可能都是丢失最后一次的写操作。
4.2 aof方式
将每次的写操作写到aof持久化文件中,默认关闭的。
开启aof的持久化方案:修改配置文件:appendonly yes
aof持久化文件 :appendfilename "appendonly.aof"
aof持久化策略:
# appendfsync always
appendfsync everysec
# appendfsync no
rdb和aof:rdb模式可以和aof同时存在,但是aof生效
5 主从复制
为了提升数据库的查询效率,解决单点故障,将数据库的读和写进行分离,所有的写操作在主数据库(master)中执行,所有的读操作在从数据库(slave)执行,为了保证数据的一致性,主数据库需要将自己的数据复制到从数据库,这个过程称之为主从复制。,主从数据库之间采用优化的二进制协议通讯,效率非常高。
主从架构: 1 master+ n slave
5.1 搭建主从复制
(1)搭建两个redis服务, 1 master和1 salve
master 6379 slave 6380
(2)启动两个redis的服务
(3)设置主从关系
slaveof host port
#在redis.conf
slaveof 127.0.0.1 6379
注意:持久化文件,不要在同一个目录下启动,给每个redis服务配置具体的确定的持久化文件目录
6 redis集群
6.1 redis集群架构
(1)每个节点之间彼此相连通讯,通讯采用的是ping/pong机制
(2)每个节点超过半数的节点没有办法实现通信则该节点fail.
(3)client和redis集中之间连接没有proxy,直接连接。client连接到任意一个节点都代表连接到整个集群
(4)cluster将整个集群划分为16384个slot(hash槽),将这些slot尽可能的均匀分布到每个节点。如果客户端需要建立与集群的连接,需要采用crc16的算法计算出hash值,然后对16384进行取余.然后将其分配到指定的节点。
6.2 投票机制
(1)某个节点是否fail
超过一半的节点都无法跟该节点进行通信,此时该节点fail。
(2)集群是否fail (slot是否完整)
①如果某个master节点fail,但是该节点下有slave,那么集群不会fail;如果没有slave,则集群fail。
②如果超过一半的master都fail,则不管是否有slave,集群都fail。
6.3 redis集群搭建
准备:①redis节点数(master)是奇数(3+);②redis是主从架构,至少需要一主一从③每个节点的master不能和该节点的slave在同一服务器
(1)准备6个redis服务(配置并启动redis服务)
daemonize yes
#bind 127.0.0.1
protected-mode no
port 6379
cluster-enabled yes
(2)搭建redis集群
①redis-trib.rb(集群管理器) : cp redis-trib.rb ~/cluster/
②安装ruby环境;yum install -y ruby yum install -y rubygems
③安装接口文件(集群管理器和redis服务之间通讯)
在线安装接口文件: gem install redis(ruby版本2.2.2+) 离线安装接口文件: gem install redis-3.2.1.gem
④搭建集群
redis-trib.rb create host1:port1 ... hostN:portN
--replicas 1
./redis-trib.rb create --replicas 1 192.168.48.101:6379 192.168.48.101:6380 192.168.48.101:6381 192.168.48.101:6382 192.168.48.101:6383 192.168.48.101:6384
连接测试:redis-cli -c:连接集群
cluster info:查看集群的整体状况 cluster nodes: 查看集群的节点状态