目录
含义:NoSQL(not only sql),意为不仅仅是sql,泛指非关系型数据库,其内部的数据存储在内存中;nosql不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大增加了数据库的扩展能力。
redis官网:https://redis.io/
进入安装目录:cd /usr/local/bin
敲击命令:redis-server
注意:前台启动后此窗口便不能再进行其他操作了,关了服务就没了
理解:该启动方式我们看不到上面的界面,并且,我们关闭窗口后那么他还可以继续使用
敲击:redis-cli
测试redis的连通状态:敲击ping后回应pong那么表示已经连通
- 为具体的key赋值为value:set key value
- 取出对应key的value值:get key
- 删除指定的key数据:del key(删除成功则返回1,否则返回0;可以清空多个)
- 删除指定的key数据:unlink key(删除成功则返回1,否则返回0)
- 注意:del直接删除,而unlink的删除他仅将其从keys内删除,真正的删除会在后续异步执行
- 查看该数据库中的所有key:keys *
- 查看key对应的value具体数据类型:type key
- 查看key是否存在:exists key(存在则返回1,否则返回0)
- 为key设置过期时间为10秒钟:expire key 10(成功则返回1,否则返回0)
- 为key设置过期时间为10000ms:pexpire key 10000(成功则返回1,否则返回0)
- 查看key的剩余过期时间:ttl key(-1表示永不过期,-2表示已过期)
- 取消key的过期时长:persist key
redis的key的数据类型为string;value的数据类型支持5种:String(字符串)、List(集合)、Set(集合)、Hash(哈希)、Zset(有序集合)
- 为key赋值为value:set key value(若key存在则value覆盖)
- 为key赋值为value:setnx key value(若key存在,则赋值失败)
- 取出key的值:get key
- 为key后面追加hello:append key hello(成功返回key的长度)
- 获得key对应value的长度:strlen key
- 为key值递增1:incr key(返回递增后的值)
- 为key值递减1:decr key(返回递减后的值)
- 为key值递增n:incrby key n(返回递增后的值)
- 为key值递减n:decrby key n(返回递减后的值)
- 注意:对于递增/递减操作,那么要递增的值必须为数字类型
- 设置k1值为v1,k2值为v2:mset k1 v1 k2 v2
- 设置k1值为v1,k2值为v2:msetnx k1 v1 k2 v2(里面的key有任何一个存在则都不会设置成功)
- 获取k1和k2的值:mget k1 k2
- 删除k1和k2的值:del k1 k2
- 获取value的范围内的字符:getrange k1 2 3(获取value的第3个到第4个间的字符,包前包后)
- 在k1的第2个索引处设置hello:setrange k1 2 hello(返回value的长度)
- 设置值时顺便设置10s过期时间:setex key 10 value
- 新值换旧值:getset key value(返回是之前的值)
String的数据结构为简单动态字符串,是可以修改的字符串,采用预分配冗余空间的方式来减少内存的频繁分配
如图所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1m时,扩容都是加倍现有空间,若超过1m,扩容时只会多扩1m的空间,但字符串value最大空间为512m
- 从左边插入多值:lpush key v1 v2 v3
- 从右边插入多值:rpush key v1 v2 v3
- 从左边吐出一个值:lpop key
- 从右边吐出一个值:rpop key
- 按照索引从左到右获得元素:lrange key 0 -1(0到-1表示取所有值)
- 从k1右边取值插入k2左边:rpoplpush k1 k2
- 根据索引下标获得指定元素:lindex key 2(获得第二个元素)
- 获取列表的长度:llen key
- 在key中v1前面插入新值:linsert key before v1 newv1(若在后面就把before换为after)
- 从左边删除n个v1:lrem key n v1
- 将列表下标为index的值替换为value:lset key index value
- 从key集合中保留下标为1到结束的数据:ltrim key 1 -1
Set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动去重的,redis的set是string类型的无序集合,他的底层其实上就是一个value为null的hash表,所以添加、删除、查找的复杂度都是O(1)
- 将多个值加入到key集合:sadd key v1 v2 v3
- 取出key集合中的值:smembers key
- 判断key集合中是否包含value:sismember key value(包含返回1,否则返回0)
- 返回key集合中元素的个数:scard key
- 删除key集合中的v1和v2:srem key v1 v2
- 随机从集合中吐出一个值:spop key
- 随机从集合中显示n个值:srandmember key n
- 把集合中的value值从k1集合移动到k2集合:smove k1 k2 value
- 返回两个集合中的交集元素:sinter k1 k2
- 返回两个集合中的并集元素:sunion k1 k2
- 返回k1集合中不包含k2的元素:sdiff k1 k2
set数据结构是dict字典,字典是用哈希表实现的,redis的内部也是使用hash结构,所有的value都指向同一个内部值
Redis hash是一个键值对集合,其是一个string类型的field和value的映射表,hash特别适用于存储对象,类似java里面的Map
- 将user对象进行存储:hset user name lili age 23(hmset也可以)
- 取出user的name:hget user name(只能取出一个属性)
- 获得user的多个属性:hmget user name age
- 取出user的所有数据:hgetall user
- 判断user的name属性是否存在:hexists user name(存在返回1,不存在返回0)
- 列出该user的所有field:hkeys user
- 列出user集合中的所有属性的值:hvals user
- 为user的age属性加2操作:hincrby user age 2
- 为user对象添加属性与值:hsetnx user sex man(若属性存在,则添加失败)
- 删除user的age与name属性:hdel user age name
Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable
zset与普通set集合十分相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分被用来按照从最低分到最高分的方式排序集合中的成员。集合中的成员是唯一的,但评分可以重复
注意:zset内的元素会默认根据score评分从小到大排序
- 将一个或多个元素以及对应的score加入到有序集合key中:zadd key 100 java 200 c++ 300 php
- 返回有序集合key下标在开始到结束之间的元素:zrange key 0 -1 [withscores]
- 注意:后面添加withscore后那么就会把他们对应的评分也显示
- 取出key中评分在150-400之间的值:zrangebyscore key 150 400 [withscores]
- 从大到小显示key中score值为700-200之间的值:zrevrangebyscore key 700 200 [withscores]
- 将key中的java元素的评分增加50:zincrby key 50 java
- 删除集合下指定值的元素:zrem key php
- 统计key中评分为100-200之间值的个数:zcount key 100 200
- 获取集合中成员的个数:zcard key
- 返回该值在集合中的索引:zrank key java
有序链表——查询慢,省空间
跳跃表(建索引)——查询快,费空间
- 设置某个偏移量的值(0/1):set key 19 1
- 理解:设置偏移量为19的地方的值为1(偏移量就理解成索引)
- 取出偏移量为1对应的值:getbit key 1(返回1下标处的值)
- 统计key偏移量在下标为[1,2]值处为1的总和:bitcount key 1 2
- 向key中加入数据:pfadd key v1 v2 v3(若value相同则添加失败,返回0,否则返回1)
- 统计key中value的数量:pfcount key
- 将k1和k2的value加到k3里:pfmerge k3 k1 k2
redis 3.2中增加了对GEO类型的支持。GEO、Geographic,地理信息的缩写。该类型就是元素的二维坐标,在地图上就是经纬度。redis基于该类型提供了经纬度设置,查询,范围查询,距离查询,经纬度hash等常见操作
- 加上海地理信息:geoadd china:city 121.47 31.23 shanghai
- 同时加上海和深圳:geoadd china:city 121.47 31.23 shanghai 114.05 22.52 shenzhen
- 获得指定地区的坐标值:geopos china:city shanghai shenzhen
- 获取两个位置之间的直线距离以km为单位:geodist chain:city shanghai shenzhen km
- 以给定的经纬度为中心,找出某一半径内的元素:georadius china:city 110 30 1000 km
- 理解:计算出东京110度北纬30度在里面方圆1000km以内的城市
注意:
配置大小单位,开头定义了一些基本的度量单位,只支持byte,不支持bit;大小写不敏感
理解:include包含其他文件内容
bind=127.0.0.1:只能接收本机的访问请求,不写的情况下无限制接收任何ip地址的访问
protect-mode no:保护模式开启情况下,redis只允许接受本机的响应
port 6379:端口号默认6379
tcp-backlog 511:backlog为一个连接队列
注意:backlog队列总和=未完成三次握手的队列+已完成三次握手的队列
timeout 0:redis连接永不超时(秒为单位)
tcp-keepalive 300:每隔300s检测一次连接是否存活
daemonize yes:是否支持redis后台启动,yes表示是
pidfile /var/run/redis_6379.pid:将进程号设置到该文件中保存
loglevel notice:设置日志级别
logfile "":设置日志的输出文件路径,默认为空
database 16:redis默认有16个库
内存淘汰策略
redis发布订阅是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息,redis客户端可以订阅任意数量的频道
理解:发送者可以发送很多频道,若订阅者订阅发布者的所有频道,那么当发布者发布时,订阅者一定能收到消息,若订阅者只订阅发布者的a频道,而发布者向b频道发送消息,那么订阅者便不能收到消息
第二个客户端就收到了
前提:配置文件中配置允许远程连接
- <dependencies>
- <!--redis客户端依赖-->
- <dependency>
- <groupId>redis.clients</groupId>
- <artifactId>jedis</artifactId>
- <version>4.2.3</version>
- </dependency>
- </dependencies>
- public static void main(String[] args) {
- //创建jedis的对象(远程访问redis服务)
- Jedis jedis = new Jedis("192.168.126.129",6379);
- //测试是否连接上redis,若成功,返回pong
- String ping = jedis.ping();
- System.out.println(ping);
- }
注意:连接时应先关闭防火墙
- public static void main(String[] args) {
- //创建jedis的对象(远程访问redis服务)
- Jedis jedis = new Jedis("192.168.126.129",6379);
- //jedis.auth("123456");密码
- //选择1号数据库
- jedis.select(1);
- //添加元素
- jedis.set("name", "lili");
- //获得该数据库下所有的key
- Set<String> keys = jedis.keys("*");
- //查看keys的个数
- System.out.println(keys.size());
- for (String key : keys) {
- System.out.println(key);
- }
- //判断name是否存在
- System.out.println(jedis.exists("name"));
- //查看name的过期时间
- System.out.println(jedis.ttl("name"));
- //获得name的值
- System.out.println(jedis.get("name"));
- //为name设置过期时间10s
- jedis.expire("name", 10);
- //删除name
- jedis.del("name");
- //设置多个key-value
- jedis.mset("age","23","sex","man");
- List<String> mget = jedis.mget("age", "sex");
- System.out.println(mget);
- jedis.close();
- }
- @Test
- public void test1(){
- //创建jedis的对象(远程访问redis服务)
- Jedis jedis = new Jedis("192.168.126.129",6379);
- //添加元素
- jedis.lpush("k1", "v1","v2","v3");
- //取出元素
- List<String> k1 = jedis.lrange("k1", 0, -1);
- System.out.println(k1);
- //其他的一样(太多了没必要)
- }
- @Test
- public void test2(){
- Jedis jedis = new Jedis("192.168.126.129",6379);
- jedis.sadd("people", "lili","lala","lan");
- Set<String> people = jedis.smembers("people");
- System.out.println(people);
- }
- @Test
- public void test3(){
- Jedis jedis = new Jedis("192.168.126.129",6379);
- jedis.hset("user", "name","lili");
- String hget = jedis.hget("user", "name");
- System.out.println(hget);
- //hmset,hmget可以操作多个
- }
- @Test
- public void test4(){
- Jedis jedis = new Jedis("192.168.126.129",6379);
- jedis.zadd("china", 100d, "shanghai");
- Set<String> china = jedis.zrange("china", 0, -1);
- System.out.println(china);
- }
注意:以上太多方法,不再一一演示,基本大同小异,照猫画虎即可
注意:依赖还是用上面的
- public static void main(String[] args) {
- //定义连接池配置
- JedisPoolConfig config = new JedisPoolConfig();
- //设置最大连接数
- config.setMaxTotal(1000);
- //设置最大空闲数
- config.setMaxIdle(60);
-
- //创建连接池对象
- JedisPool jedisPool = new JedisPool(config,"192.168.126.129",6379);
- //从池中获取连接
- Jedis resource = jedisPool.getResource();
- //resource.auth("root");密码
- String ping = resource.ping();
- System.out.println(ping);
- resource.close();
- jedisPool.close();
- }
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <!--redis依赖-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <!--spring集成redis所需要的连接池依赖-->
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-pool2</artifactId>
- <version>2.6.0</version>
- </dependency>
- </dependencies>
- #application.yml文件内
- server:
- port: 8080
- spring:
- redis:
- host: 192.168.126.129
- port: 6379
- #redis的默认数据库
- database: 0
- timeout: 1800000
- lettuce:
- pool:
- #连接池最大连接数:20
- max-active: 20
- #最大等待时间
- max-wait: -1
- #最大空闲连接数
- max-idle: 5
- #最小空闲连接数
- min-idle: 0
- @EnableCaching
- @Configuration
- public class RedisConfig extends CachingConfigurerSupport {
-
- @Bean
- public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
- RedisTemplate<String, Object> template = new RedisTemplate<>();
- RedisSerializer<String> redisSerializer = new StringRedisSerializer();
- Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
- ObjectMapper om = new ObjectMapper();
- om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jackson2JsonRedisSerializer.setObjectMapper(om);
- template.setConnectionFactory(factory);
- //key序列化方式
- template.setKeySerializer(redisSerializer);
- //value序列化
- template.setValueSerializer(jackson2JsonRedisSerializer);
- //value hashmap序列化
- template.setHashValueSerializer(jackson2JsonRedisSerializer);
- return template;
- }
-
- @Bean
- public CacheManager cacheManager(RedisConnectionFactory factory) {
- RedisSerializer<String> redisSerializer = new StringRedisSerializer();
- Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
- //解决查询缓存转换异常的问题
- ObjectMapper om = new ObjectMapper();
- om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jackson2JsonRedisSerializer.setObjectMapper(om);
- // 配置序列化(解决乱码的问题),过期时间600秒
- RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
- .entryTtl(Duration.ofSeconds(600))
- .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
- .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
- .disableCachingNullValues();
- RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
- .cacheDefaults(config)
- .build();
- return cacheManager;
- }
- }
- @Autowired
- private RedisTemplate redisTemplate;
- @Test
- void contextLoads() {
- //基于字符串操作对象
- ValueOperations value = redisTemplate.opsForValue();
- //设置值
- value.set("name", "lili");
- //从redis内获取值
- String name = (String) value.get("name");
- System.out.println(name);
- }
- @Autowired
- private RedisTemplate redisTemplate;
- @Test
- public void test1(){
- //基于hash操作对象
- HashOperations hash = redisTemplate.opsForHash();
- //设置值
- hash.put("user", "name", "lili");
- //取值
- Map user = hash.entries("user");
- System.out.println(user);
- }
- @Autowired
- private RedisTemplate redisTemplate;
- @Test
- public void test2(){
- //基于list操作
- ListOperations list = redisTemplate.opsForList();
- list.leftPush("k1", "v1");
- list.leftPushAll("k1", "k2","k3");
- List k1 = list.range("k1", 0, -1);
- System.out.println(k1);
- }
- @Autowired
- private RedisTemplate redisTemplate;
- @Test
- public void test3(){
- SetOperations set = redisTemplate.opsForSet();
- set.add("setKey1", "A","B","C","C");
- Object members=set.members("setKey1");
- System.out.println("setKeys="+members);
- }
含义:redis事务是一个单独的隔离操作:事务中的所有命令都会被序列化,按照顺序的执行。事务在执行过程中,不会被其他客户端发送来的命令请求所打断
redis事务的主要作用:串联多个命令,防止别的命令插队
从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,redis会将之前的命令队列中的命令依次执行
注意:
注意:使用时先引入redis客户端依赖
- public static void main(String[] args) {
- Jedis jedis = new Jedis("192.168.126.129",6379);
- jedis.set("tony", "300");
- //监视tony
- jedis.watch("tony");
- //开启事务
- Transaction multi = jedis.multi();
- try {
- multi.incrBy("tony", 100);
- multi.exec();
- }catch (Exception ex){
- //若抛异常则取消事务
- multi.discard();
- }finally {
- jedis.close();
- }
- }
注意:只要在key值被监视和提交事务之间的时间段内name值发生变化,那么提交后的返回值为nil
在并发执行时,为了更好的保证事务的4个特性,通常会对事务加锁,redis为了性能采用了乐观锁的方式进行事务控制,它使用watch命令监视给定的key,当exec时,若监视的key从调用watch后发生了变化,则整个事务会失败。也可以调用watch多次监视多个key。
注意:
持久化:把内存中的数据写到磁盘中
持久化原因:redis为内存数据库,内存中的东西在断电时可能会丢失
含义:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的快照,它恢复时是将快照直接读到内存中
redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束,再用这个临时文件替换掉之前的文件。整个过程中,主进程不进行任意的io操作,这就确保了极高的性能;若需要进行大规模数据恢复,且对于数据恢复的完整性不是非常敏感,那么RDB的方式要比AOF的方式更加高效。RDB的唯一缺点就是最后一次持久化的数据可能丢失
redis持久化后会生成一个文件,文件名字默认为dump.rdb,但redis并不是直接就把数据写到dump.rdb文件中,而是先创建一个子进程(进程名为fork),然后,当持久化时先在里面创建一个临时的文件,先将数据同步到临时区域中,当数据同步完成之后便会将里面的内容覆盖到dump.rdb文件中(目的:防止数据不完整)——(写时复制技术)
dbfilename dump.rdb:持久化文件名为dump.rdb
dir ./:在redis的启动目录(/usr/local/bin)中生成这个rdb文件
stop-writes-on-bgsave-error yes:当redis无法写入磁盘的话,那么直接关闭redis的写操作
rdbcompression yes:持久化文件时,持久化文件进行压缩操作
rdbchecksum yes:检查数据的完整性(是否损坏)
save 60 1000:每隔60s至少有1000个key发生变化,那么就生成一个dump.rdb快照
含义:通过记录写操作日志的方式记录redis数据的一种持久化机制,此机制默认是关闭的,此方式将每一个收到的命令都通过wiite函数增加到日志文件的最后(读操作不记录),redis重启会读取该文件,重新构建数据
appendonly yes:AOF文件开启(默认为no)
appendfilename "appendonly.aof":AOF文件名为appendonly.aof
appendfsync everysec:每秒记录日志一次,若宕机,本秒内的数据可能丢失
no-appendfsync-on-rewrite yes:在重写期间,对新写入的不进行持久化,暂存在内存中,重写完再持久化
auto-aof-rewrite-percentage 100:文件达到100%时重写启动
auto-aof-rewrite-min-size 64mb:AOF日志文件启动重写的文件最小值为64mb
注意:
AOF采用文件的追加方式,文件会越来越大为避免此种情况,新增了重写机制,当AOF文件的大小超过了所设定的阈值,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后在rename),redis4.0版本后的重写,实质上就是把rdb的快照以二进制的形式附在新的aof的头部,作为已有的历史数据,替换掉原来的流水账操作
主进程fork出子进程进行重写,子进程遍历redis内存中的数据到临时文件,子进程写完该临时文件后向主进程发信号,由主进程把该临时文件中的数据写入到新的aof文件中,进而用新aof文件替换就aof文件
注意:官方推荐用dump.rdb作为第一步的数据恢复,然后用appendonly.aof作为第二步的数据增量
含义:主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主(也可以读),slave以读为主(只能读)
关闭AOF:appendonly no(不关也可以,AOF文件改个名,别都一样)
复制redis.conf文件到myredis(文件夹名随意起)文件夹中起名也叫redis.conf
创建3个配置文件:redis6379.conf、redis6380.conf、redis6381.conf
在3个配置文件中按照格式写入内容
- #从外面引入redis.conf配置文件
- include /root/myredis/redis.conf
- #将该文件的进程号设置到该路径保存
- pidfile /var/run/redis_6379.pid
- #设置端口号
- port 6379
- #设置持久化rdb文件名
- dbfilename dump6379.rdb
启动三台redis服务器
通过端口号连接redis:redis-cli -p 6379
启动三台redis,查看三台主机的运行情况:info replication
由此观之三台机器全是主机
配置主从(我要6379为主节点)
除了6379端口以外的服务执行命令:slaveof 主节点ip地址 主节点端口号(slaveof 127.0.0.1 6379)
由此观之成功(主机可以读写,从机只能读)
注意:
薪火相传:一个主服务器,一个次主服务器,一个从服务器;从服务器只能从次主服务器中同步数据,次主服务器只能从主服务器中同步数据(白话:一个从服务器再挂一个从服务器)
反客为主:当一个master宕机后,后面的slave可以立即升为master,其后面的salve不用做任何修改(薪火相传的前提下,次主服务器升主)
(反客为主)主机挂掉后敲击命令:slaveof no one
含义:反客为主自动版,能够后台监控主机是否故障,若故障了则根据投票数自动将从库转为主库
自定义/myredis(特定目录下就可以)目录下新建sentinel.conf文件(名字必须为这个)
- sentinel monitor mymaster 127.0.0.1 6379 1
- #注意:mymaster为给监控对象起的名称,1为至少有多少个哨兵同意迁移的数量
启动哨兵:redis-sentinel sentinel.conf
注意:若哨兵选出了新主服务器,那么原主机若重启则会为新主机的从服务器
- sentinel monitor mymaster 127.0.0.1 6380 1
- #后台运行
- daemonize yes
- #运行日志所在文件
- logfile "/root/myredis/sentinel_log.log"
- #主节点失效30秒后被认为失效
- sentinel down-after-milliseconds mymaster 30000
启动哨兵:redis-sentinel sentinel.conf
注意:无中心化集群(任何一台服务器都可以作为集群的入口)
制作6个实例,6379、6380、6381、6389、6390、6391(文件名随意:redis端口号.conf)
关闭AOF:appendonly no(不关也可以,AOF文件改个名,别都一样)
复制redis.conf文件到myredis(文件夹名随意起)文件夹中起名也叫redis.conf
在6个配置文件中按格式写如下内容
- include /root/myredis/redis.conf
- pidfile "/var/run/redis_6379.pid"
- port 6379
- dbfilename "dump6379.rdb"
- #开启集群
- cluster-enabled yes
- #集群配置文件名字
- cluster-config-file node-6379.conf
- #设置节点失联时间,超过该时间集群节点会自动进行主从切换
- cluster-node-timeout 15000
使用查找替换修改另外5个文件(:%s/6379/6380)
理解:将linux文件内的6379转换为6380
启动6个redis服务:(redis-server redis6379.conf)
将6个节点合成一个集群
注意:组合之前,应确保所有的redis实例启动后,nodes-xxxx.conf文件都能正常生成
合体:
进入之前redis的解压目录的src目录:/root/redis-7.0.4/src/在该目录里执行命令:
redis-cli --cluster create --cluster-replicas 1 192.168.126.129:6379 192.168.126.129:6380 192.168.126.129:6381 192.168.126.129:6389 192.168.126.129:6390 192.168.126.129:6391
注意:
由此观之:因为我的create --cluster-replicas 1配置导致自动实现3主三从的最简单方式
注意:若集群中的主节点挂掉,那么从节点便会升为主节点,若主节点再启动,那么他会变为从机
之前我已经说过,该集群为无中心化集群(任何一个节点都可以作为集群的入口,并且他们之间可以互相访问)
集群连接:redis-cli -c -p 6379
注意:-c表示集群方式连接,集群方式连接用任何一个节点都可以
在节点内查看集群中节点的信息:cluster nodes
注意:最后面有插槽信息,请仔细看(一主一从分配一段插槽范围)
在节点内查看集群基本的信息:cluster info
查看key的插槽值:cluster keyslot key
查看5474插槽内有多少key:cluster countkeysinslot 5474
在5474插槽中返回10个slot的键:cluster getkeysinslot 5474 10
前提:添加redis客户端依赖
- public static void main(String[] args) {
- //创建对象
- //集群入口节点——当然,也可以创建一个set集合放入多个地址与端口号的hostAndPost,但redis集群是无中心化的,所以一个就够了
- //用任何一个节点都能连上我们的集群
- HostAndPort hostAndPort = new HostAndPort("192.168.126.129", 6379);
- JedisCluster jedisCluster = new JedisCluster(hostAndPort);
-
- //进行操作
- jedisCluster.set("k1", "v1");
- String k1 = jedisCluster.get("k1");
- System.out.println(k1);
- jedisCluster.close();
- }