Redis是完全开源免费的,是一个高性能并具有持久化功能的key-value缓存数据库.
特点
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
Redis支持数据的备份,即master-slave主从模式的数据备份。
性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
Redis 5主要专注于几个重要功能。相比之下Redis 4非常非常专注于操作类型,Redis 5的变化大多是面向用户的。即在现有的基础上增加新的数据类型和操作类型。
以下是此版本的主要功能:
1.新的Stream数据类型。
2.新的Redis模块API:Timers and Cluster API。
3. RDB现在存储LFU和LRU信息。
4.集群管理器从Ruby(redis-trib.rb)移植到C代码。可以在redis-cli中。查看redis-cli cluster help了解更多信息。
5.新sorted set命令:ZPOPMIN / MAX和阻塞变量。
6.主动碎片整理V2。
7.增强HyperLogLog实现。
8.更好的内存统计报告。
9.许多带有子命令的命令现在都有一个HELP子命令。
10.客户经常连接和断开连接时性能更好。
11.错误修复和改进。
12.Jemalloc升级到5.1版
(1) 读写分离
在redis主从架构中,Master节点负责处理写请求,Slave节点只处理读请求。对于写请求少,读请求多的场景,例如电商详情页,通过这种读写分离的操作可以大幅提高并发量,通过增加redis从节点的数量可以使得redis的QPS达到10W+。
(2) 主从同步
Master节点接收到写请求并处理后,需要告知Slave节点数据发生了改变,保持主从节点数据一致的行为称为主从同步,所有的Slave都和Master通信去同步数据也会加大Master节点的负担,实际上,除了主从同步,redis也可以从从同步。
1、解压Redis
tar xzvf /usr/redis/redis-5.0.3.tar.gz -C /usr
mv redis-5.0.3 redis
2、编译及安装
[root@localhost redis]# make
[root@localhost redis]# make install
##设置内存分配策略(略)
3、单实例启动(6379服务)
/usr/redis/redis-6379/bin/redis-server /usr/redis/redis-6379/conf/redis.conf
4、客户端连接
/usr/redis/redis-6379/bin/redis-cli 或
/usr/redis/redis-6379/bin/redis-cli -h 127.0.0.1 -p 6379 -a 123456
5、退出客户端、退出Redis服务
#查看、关闭Redis服务
ps -ef|grep redis 或 netstat -nltp
killall redis-server
pkill redis-server
1、创建用于Redis启动程序、配置文件、运行的pid、日志logs、数据文件存储等目录
mkdir -p /usr/redis/{redis-6379,redis-6380,redis-6381}/{bin,conf,run,logs,dbcache}
2、复制应用程序
cp /usr/redis/src/{redis-server,redis-cli,redis-benchmark} /usr/redis/redis-6379/bin
cp /usr/redis/src/{redis-server,redis-cli,redis-benchmark} /usr/redis/redis-6380/bin
cp /usr/redis/src/{redis-server,redis-cli,redis-benchmark} /usr/redis/redis-6381/bin
复制redis.conf到redis-6379/conf/目录
cp /usr/redis/redis.conf /usr/redis/redis-6379/conf/
cd /usr/redis/redis-6379/conf/
mv redis.conf redis-6379.conf
vi redis-6379.conf
#三个conf文件公共配置
#bind 127.0.0.1 #开启外网访问
requirepass 123456 #三个Redis密码
daemonize yes #开启后台运行
#修改端口、pid文件、日志文件、数据文件路径
port 6379
pidfile /usr/redis/redis-6379/run/redis_6379.pid
logfile "/usr/redis/redis-6379/logs/redis.log"
dir /usr/redis/redis-6379/dbcache/
复制一份到6380
cp redis-6379.conf /usr/redis/redis-6380/conf/
cd /usr/redis/redis-6380/conf/
mv redis-6379.conf redis-6380.conf
vim redis-6380.conf
:1,$s/6379/6380/g #vim替换命令
#修改端口、pid文件、日志文件、数据文件路径
port 6380
pidfile /usr/redis/redis-6380/run/redis_6381.pid
logfile "/usr/redis/redis-6380/logs/redis.log"
dir /usr/redis/redis-6380/dbcache/
#主从设置
masterauth 123456 #设置从库访问master密码
#replicaof
replicaof 192.168.4.165 6379 #从库连接主库的IP地址
复制一份到6381
cp redis-6380.conf /usr/redis/redis-6381/conf/
cd /usr/redis/redis-6381/conf/
mv redis-6380.conf redis-6381.conf
vi redis-6381.conf
:1,$s/6380/6381/g #vim替换命令
#修改端口、pid文件、日志文件、数据文件路径
port 6381
pidfile /usr/redis/redis-6381/run/redis_6381.pid
logfile "/usr/redis/redis-6381/logs/redis.log"
dir /usr/redis/redis-6381/dbcache/
#主从设置
masterauth 123456 #设置从库访问master密码
#replicaof
replicaof 192.168.4.165 6379 #从库连接主库的IP地址
/usr/redis/redis-6379/bin/redis-server /usr/redis/redis-6379/conf/redis-6379.conf
/usr/redis/redis-6380/bin/redis-server /usr/redis/redis-6380/conf/redis-6380.conf
/usr/redis/redis-6381/bin/redis-server /usr/redis/redis-6381/conf/redis-6381.conf
/usr/redis/redis-6379/bin/redis-cli -h 192.168.4.165 -p 6379 -a 123456 info replication
或
/usr/redis/redis-6379/bin/redis-cli -h 192.168.4.165 -p 6379 -a 123456
192.168.4.165:6379> info replication
[root@localhost redis-6379]# /usr/redis/redis-6379/bin/redis-cli -h 192.168.4.165 -p 6379 -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
#Replication
role:master
connected_slaves:2
slave0:ip=192.168.4.165,port=6380,state=online,offset=252,lag=1
slave1:ip=192.168.4.165,port=6381,state=online,offset=266,lag=0
master_replid:ad0255eaf4d0d1468d3bb0a8e1fe519fda625097
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:266
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:266
主节点:set添加数据
主节点:退出
从节点:登录
从节点:set添加数据(只读状态read only)
Jedis
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisConnectionPool {
public static final String REDIS_HOST="192.168.4.165";
public static final int REDIS_PORT=6379;
public static final int TIMEOUT=2000;
public static final String REDIS_AUTH="123456";
//注掉redis.conf中的bind 127.0.0.1
public static void main(String args[])throws Exception
{
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(1000);//最大连接数
poolConfig.setMaxIdle(200); //最小维持连接数
poolConfig.setMaxWaitMillis(1000);//最大等待时间
poolConfig.setTestOnBorrow(true);//是否进行连接测试,以保证返回的连接为可用连接
//
JedisPool pool = new JedisPool(poolConfig, REDIS_HOST, REDIS_PORT, TIMEOUT, REDIS_AUTH);
Jedis jedis = pool.getResource();
//
System.out.println(jedis.ping());
System.out.println(jedis.keys("*"));
//set get
jedis.set("id","1001");
jedis.set("name","zsan");
jedis.set("level","1");
System.out.println(jedis.get("id")+", "+jedis.get("name")+", "+jedis.get("level"));
//setex
jedis.setex("phone", 5, "15029200344");
Thread.sleep(3000);
System.out.println(jedis.ttl("phone")); //5秒后获取有效时间
System.out.println(jedis.get("phone"));
Thread.sleep(2000);
System.out.println(jedis.get("phone")); //null
//hset
jedis.hset("dept","id","1001");
jedis.hset("dept","name","张三");
jedis.hset("dept","level","1");
System.out.println(jedis.hget("dept","name")); //utf-8编码
System.out.println(jedis.hgetAll("dept"));
//list
jedis.lpush("book", "Redis","Mysql","Oracle","SqlServer");
List books = jedis.lrange("book",0,-1);
jedis.rpush("books", "SpringBoot");
System.out.println(books);
//Set
jedis.sadd("animal", "Tiger","giraffe","Elephant","Bear");
Set animals = jedis.smembers("animal");
//jedis.rpush("books", "SpringBoot");
System.out.println(animals);
//SortSet
Map map = new HashMap<>();
map.put("1001", 60.0);
map.put("1002", 79.5);
map.put("1003", 90.0);
map.put("1004", 98.0);
jedis.zadd("score", map);
Set scores = jedis.keys("score");
System.out.println(scores);
//
jedis.close();
}
}
Redis 主从架构搭建及原理详解
https://www.jianshu.com/p/f0e042b95249
Redis 5.0之后版本的高可用集群搭建
https://www.jianshu.com/p/8045b92fafb2