作用
redis用作数据库、缓存、消息中间件(k-v),支持多种类型的数据结构:字符串(Strings)、散列(hashs)、列表(lists)、集合(sets)、有序集合(sorted sets)、范围查询。
安装
redis压缩包提取码:oy2z
- 上传redis压缩包到/usr/local/src/目录下解压后删除压缩包并修改名为redis
- 进入redis根目录后,编译和安装redis
命令 | 作用 |
---|---|
make | 编译 |
make install | 安装 |
在redis根目录执行redis执行redis-server出现下面logo即为安装成功,ctrl+c退出
Redis配置文件的修改
命令: vim redis.conf
1.关闭IP绑定: #bind 127.0.0.1 (69行)
2.关闭保护模式: protected-mode no (88行)
3.开启后台启动:daemonize yes (136行)
常规命令:redis-server redis.conf
查看redis是否启动:ps -ef|grep redis
客户端命令:redis-cli -p 6379
退出客户端:exit/quit/ctrl+c
关闭redis:redis-cli -p 6379 shutdown或者kill -9 redis运行的进程号
redis命令
如果执行redis操作,需要进入到redis客户端中执行
作用 | 命令 |
---|---|
添加k-v | set k v |
根据k获取v | get k |
获取k的长度 | strlen k |
判断k是否存在(返回1存在,0不存在) | exits k |
删除 k | del k |
查询全部数据 | keys * |
查询k为a的数据 | keys a |
查询以a开头2位长度的数据 | keys a? |
查询以a开头的任意长度数据 | keys a* |
查询第二位是a的任意长度的数据 | keys ?a* |
赋值多个k-v | mset key1 v1 key2 v2 key3 v3 |
获取多个key的值 | mget key1 key2 key3 |
对某个k的值进行追加 | append k “v” |
检查某个key的类型 | type k |
切换redis数据库(redis共有16个数据库,select 0是切换到第一个数据库) | select 0~15 |
清空单个数据库 | flushdb |
清空全部数据库 | flushall |
k的值自动加1 | incr k |
k的值自动减1 | decr k |
k的值自动加100 | incrby k 100 |
k的值自动减50 | decrby k 50 |
k在一分钟后失效(以秒为单位) | expire k 60 |
查看k的剩余存活时间 | ttl k |
撤销k的失效时间 | persist k |
如果k不存在则赋值v,如果k存在则跳过 | setnx k v |
不管k是不是已经存在都赋值v(后面的覆盖之前的操作) | set k v |
Redis入门案例
- 添加jar包文件
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!--添加spring-datajar包 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.4.1.RELEASE</version>
</dependency>
Jedis jedis=null;
@BeforeEach //当执行test测试方法执行前会先执行有@BeforeEach注解的方法,然后才会执行真正的test方法
public void init() {
String ip="192.168.80.128";//linux的ip地址
int port=6379;
jedis=new Jedis(ip,port);
}
@Test
public void testSpring() {
//redis中的操作命令就是调用的方法
String result = jedis.set("brrby", "511323199811232810");
System.out.println("结果:"+result);
String value = jedis.get("brrby");
System.out.println("获取value:"+value);
}
/**
* 要求:
* 如果redis中已经存在了这个key,则不允许赋值
*/
@Test
public void set() {
if(!jedis.exists("brrby")) {
jedis.set("brrby", "ok");
}
System.out.println(jedis.get("brrby"));
}
@Test
public void setnx() {
jedis.setnx("brrby","new");
System.out.println(jedis.get("brrby"));
}
@Test
public void param() {
SetParams params=new SetParams();
params.nx().ex(20);
//满足已存在就不能赋值和过期的原子性操作
jedis.set("brrby", "string终极(nx ex )", params);
System.out.println(jedis.get("brrby"));
System.out.println("剩余时间:"+jedis.ttl("brrby"));
}
redis分片
- 创建shards目录
- 复制配置文件到shards目录中
cp redis.conf shards/6379.conf
cp redis.conf shards/6380.conf
cp redis.conf shards/6381.conf
- 修改服务端口号:按照各自的文件修改对应的端口号信息(92行)
默认端口号是6379,所以6379.conf不用改
vim 6380.conf
vim 6381.conf
- 启动这三台redis
redis-server 6379.conf
redis-server 6380.conf
redis-server 6381.conf - 启动后查看这三台redis是否正常启动
ps -ef|grep redis
- 单元测试ShardedJedis API
redis分片后,封装一个JedisShardInfo的list集合,把redis的分片加入到集合,最后通过shardedJedis API来操作。
/**
* 每个redis中保存的数据一定都是不一样的
*/
@Test
public void testShards() {
List<JedisShardInfo> shards=new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo("192.168.80.128",6379));
shards.add(new JedisShardInfo("192.168.80.128",6380));
shards.add(new JedisShardInfo("192.168.80.128",6381));
ShardedJedis shardedJedis=new ShardedJedis(shards);
shardedJedis.set("1910", "分片test");
System.out.println(shardedJedis.get("1910"));
}
redis分片原因
单台redis不能保存海量的用户数据。如果有大量的内存数据需要保存到redis中,一般采用分片的机制运行。使用redis分片实现内存数据的扩容。
redis分片原理
特性方法——Hash一致性算法
常见hash:232种可能性(一共有32个二进制位,每个二进制位取的值只有01)
-
Hash的特点:
-
- 相同的key,hash结果相同
- Hash算法的时间复杂度n(使用hash算法无论算多大的数据计算的时间几乎没有差别)
redis数据存储规则:
node=hash(ip+端口号)
- 均衡性:hash一致性中利用均衡性,实现了数据的平衡。具体操作时采用虚拟节点的概念实现的。(由于hash算法没有任何指向性,会导致某一个节点的数据会很多,某些节点的数据又很少)
- 单调性:当节点新增时,利用单调性的规则会实现数据的动态的迁移,保证数据的平衡。同时满足他节点尽可能保证数据不变。无需人为的干预。(特点说明:redis中的节点只能新增不能减少,如果节点减少后则需要重新hash)
redis分片问题说明
使用redis分片时,假如某一个redis节点宕机将直接影响redis分片的使用
解决:实现主从复制,内存数据的复制,停止分片机制,使用哨兵机制(分片机制和哨兵机制属于不同的实现逻辑。为了不产生干扰,需要将分片的配置全部关闭)
redis哨兵机制
-
复制shard文件目录改名为sentinel,删除其中的rdb文件,启动sentinel中的三台服务器
-
配置三台服务器的主从关系(6379主机 6380/6381从机)
如果主机中set数据,从机就会实时地同步内存数据。默认每个服务器自己都是master。
2.1. 检查节点状态信息:info replication
2.2. 挂载:slaveof redis部署的系统ip地址 port
-
编辑哨兵的配置文件:
3.1. 将哨兵的配置文件sentinel.conf复制到sentinel目录中
cp sentinel.conf sentinel
3.2. 编辑修改sentinel.conf文件
(1)关闭保护模式,17行修改为:protected-mode no
(2)开启后台启动,26行修改为:daemonize yes
(3)修改哨兵的监听:84行修改为:sentinel monitor mymaster [linux ip] 6379 1
(4)修改超时时间:主机宕机多少秒之后,开始推选.(默认30秒,修改成10秒)
-
启动哨兵命令:redis-sentinel sentinel.conf
5.单元测试Redis哨兵API
/**
* 实现Redis哨兵的配置
*/
@Test
public void testSentinel() {
String masterName="mymaster";
//准备哨兵的集合配置 IP:PORT
Set<String> sentinels=new HashSet<>();
sentinels.add("192.168.80.128:26379");
JedisSentinelPool sentinelPool = new JedisSentinelPool(masterName, sentinels);
Jedis resource = sentinelPool.getResource();
resource.set("1910", "哨兵操作ok");
System.out.println(resource.get("1910"));
resource.close();
}
哨兵会定期向主机发送心跳检测(PING- PONG) ,如果主机连续3次没有返回数据(PONG) .哨兵断定主机宕机了.哨兵监听主机的同时,会记录主机的全部的主从状态信息,Info replication就可以查看。根据选举机制,选择新的主机。如果哨兵选举了新的主节点,那么其他节点将动态的修改主从的配置,充当新节点的从机。
总结哨兵与分片
分片:实现内存扩容
哨兵:实现节点的高可用
分片与哨兵没有任何关系
redis终极形态——redis的集群