Redis

Linux下安装Redis

安装包地址:http://download.redis.io/releases/redis-6.0.5.tar.gz

将下载好的安装包进行解压

tar -zxvf redis-6.0.5.tar.gz

解压后进行基本的环境安装

yum install gcc-c++
make
make install

redis默认安装路径为

/usr/local/bin

将配置文件redis.conf复制到redis安装路径下

cp /opt/redis-6.0.5/redis.conf config

修改redis后台默认启动项daemonize 改为yes

vim redis.conf
daemonize yes
:wq

启动Redis(通过指定的配置文件)

redis-server redis.conf

客户端连接

redis-cli -p 6379

测试

127.0.0.1:6380> ping
PONG
127.0.0.1:6380>

停止服务并退出

shutdown
exit

redis基本操作命令

select index            #切换不同的redis库
flushdb   #清空当前redis库
flushall #清空全部的redis库
dbsize #查看当前库大小
keys * #查询当前库所有的key
exists key #判断当前key是否存在
move key index #移动当前key到指定的redis库中
expire key seconds #设置一个key的过期的秒数
ttl key #查看当前key剩余过期时间
type key #查看当前key的值什么类型

redis五大数据类型

String(字符串)

set key value                       #插入值
get key #获取值
append key value #字符串追加 (当追加的key不存在时,操作为新set一个key)
strlen key #获取字符串的长度
incr key #自增1(i++)
decr key #自减1(i--)
incrby key #步长增i
decrby key #步长减i
getrange key start end #返回key对应的字符串value的子串
setrange key offset value #覆盖value值中的字符串
setex key seconds value #设置key-value并设置过期时间(单位:秒)
setnx key value #设置的一个key的value,只有当该key不存在时
mset key value [key value ...] #设置多个key-value
mget key [key ...] #获取多个key的value值
getset key value #先获取这个key后赋值给这个key新的value值

 

List(列表)

RPUSH key value [value ...]                     #从列表的右边插入一个或多个元素
LPUSH key value [value ...] #从列表的左边插入一个或多个元素
LRANGE key start stop #从列表中获取指定索引返回的元素
RPOP key #从列表的右边移除一个元素
LPOP key #从列表的左边移除一个元素
LINDEX key index #通过其索引获取一个元素
LLEN key #获得列表索引长度
LREM key count value #从列表中删除元素(count代表移除相同value个数)
LTRIM key start stop #截取到指定范围内的value
RPOPLPUSH source destination #删除列表中的最后一个元素,将其追加到另一个列表(source 旧列表;destination 新列表)
LSET key index value #更改列表里面指定索引元素的值
LINSERT key BEFORE|AFTER pivot value #在列表中的另一个元素(pivot)之前或之后插入一个元素

Set(集合)

set无序不可重复

SADD key member [member ...]                                          #添加一个或者多个元素到集合(set)里(member代表集合元素)
SMEMBERS key #获取集合里面的所有元素
SISMEMBER key member #判断给定的值是否存在该集合中
SCARD key #获取集合里面的元素数量
SRANDMEMBER key [count] #从集合里面随机获取一个元素
SPOP key [count] #随机删除集合里面的某一个元素
SMOVE source destination member    #移动集合里面的一个元素到另一个集合
SDIFF key [key ...] #获取多个集合中不同元素(差集)
SINTER key [key ...] #获取多个集合中所有相同元素(交集)
SUNION key [key ...] #获取多个集合中所有元素(并集)

Hash(哈希)

map集合,key-<key,value>

HSET key field value                                            #设置hash里面一个字段的值
HGET key field #获取hash中field的值
HGETALL key #从hash中读取全部的field和值
HMSET key field value [field value ...] #设置hash里面多个字段值
HMGET key field [field ...] #获取hash里面多个指定field的值
HDEL key field [field ...] #删除一个或多个Hash的field
HLEN key #获取hash里所有field的数量
HEXISTS key field #判断hash中是否存在field
HKEYS key #获取hash的所有field
HVALS key #获得hash的所有values
HINCRBY key field increment #将hash中指定value的值增加给定的数字(increment)
HSETNX key field value #设置hash的field,只有当这个field不存在时才创建

Zset(有序集合)

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]        #添加到有序set的一个或多个成员,或更新的分数,如果它已经存在
ZRANGE key start stop [WITHSCORES] #根据指定的index返回,返回sorted set的成员列表
ZREVRANGE key start stop [WITHSCORES] #在排序的设置返回的成员范围,通过索引,下令从分数高到低
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] #返回有序集合中指定分数区间内的成员,分数由低到高排序(min:-inf;max:+inf)
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] #返回有序集合中指定分数区间内的成员,分数由高到低排序(min:-inf;max:+inf)
ZREM key member [member ...] #从排序的集合中删除一个或多个成员
ZCARD key #获取一个排序的集合中的成员数量
ZCOUNT key min max #返回分数范围内的成员数量

三种特殊类型

Geospatial(地理空间)

定位、附近的人、地点距离

GEOADD key longitude latitude member [longitude latitude member ...]              #添加一个或多个地理空间位置到sorted set(经度 纬度 地点)
GEOPOS key member [member ...] #返回地理空间的经纬度
GEODIST key member1 member2 [unit] #返回两个地理空间之间的距离(unit:单位:m|km|ft|mi)
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] #查询指定半径内所有的地理空间元素的集合
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] #查询指定半径内匹配到的最大距离的一个地理空间元素。
GEOHASH key member [member ...] #返回一个标准的地理空间的Geohash字符串
ZRANGE key start stop [WITHSCORES] #根据指定的index返回,返回sorted set的成员列表
ZREM key member [member ...] #从排序的集合中删除一个或多个成员

Hypeloglog

PFADD key element [element ...]                                             #将指定元素添加到HyperLogLog
PFCOUNT key [key ...] #返回HyperLogLog在键处观察到的集合的近似基数
PFMERGE destkey sourcekey [sourcekey ...] #将多个不同的HyperLogLog合并为一个HyperLogLog

Bitmaps

SETBIT key offset value                                                           #设置或清除存储在key的字符串值中偏移的位
GETBIT key offset #返回位的值存储在关键的字符串值的偏移量
BITCOUNT key [start end] #统计字符串指定起始位置的字节数

事务

事务的本质是 一组命令共同执行的集合,在执行的过程中会存在序列化操作,每条命令会按照顺序执行、其次执行时不运行被其他所干扰。

单条记录能保证事务的原子性,但redis事务不能保证事务的原子性,其次没有隔离性概念

127.0.0.1:6379[3]> MULTI  #开启事务
OK
127.0.0.1:6379[3]> set k1 v1
QUEUED #排队中
127.0.0.1:6379[3]> set k2 v2
QUEUED
127.0.0.1:6379[3]> get k2
QUEUED
127.0.0.1:6379[3]> set k3 v3
QUEUED
127.0.0.1:6379[3]> EXEC #执行事务
1) OK
2) OK
3) "v2"
4) OK

 

编译型异常出现的话,整组事务都不会被执行,在执行事务操作时会抛出异常

127.0.0.1:6379[3]> MULTI
OK
127.0.0.1:6379[3]> set k1 v1
QUEUED
127.0.0.1:6379[3]> set k2 v2
QUEUED
127.0.0.1:6379[3]> getset k2
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379[3]> set k4 v4
QUEUED
127.0.0.1:6379[3]> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379[3]>

 

运行时异常出现不会影响事务

127.0.0.1:6379[3]> multi
OK
127.0.0.1:6379[3]> set k1 v1
QUEUED
127.0.0.1:6379[3]> incr k1
QUEUED
127.0.0.1:6379[3]> set k2 v2
QUEUED
127.0.0.1:6379[3]> get k2
QUEUED
127.0.0.1:6379[3]> set k3 v3
QUEUED
127.0.0.1:6379[3]> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "v2"
5) OK
127.0.0.1:6379[3]> get k2
"v2"
127.0.0.1:6379[3]> get k3
"v3"
127.0.0.1:6379[3]>

 

MULTI                       #标记一个事务块开始
EXEC #执行所有 MULTI 之后发的命令
DISCARD #丢弃所有 MULTI 之后发的命令

Redis实现乐观锁操作 watch

Jedis

maven依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>3.3.0</version>
</dependency>

代码测试

import redis.clients.jedis.Jedis;
public class Testjedis {
   public static void main(String[] args) {
       Jedis jedis = new Jedis("127.0.0.1",6379);
       System.out.println(jedis.ping());
  }
}

结果

PONG

Process finished with exit code 0

Springboot-Redis

maven依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
   <version>2.3.1.RELEASE</version>
</dependency>

代码测试

@SpringBootTest
class Redis02SpringbootApplicationTests {
   @Autowired
   private RedisTemplate redisTemplate;
   @Test
   void contextLoads() {
       redisTemplate.opsForValue().set("name","zhangsan");
       System.out.println(redisTemplate.opsForValue().get("name"));
  }
}

结果

zhangsan

RedisTemplate

自定义RedisTemplate实现序列化操作


@Configuration
public class RedisConfig {
   @Bean
   public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
       /* 我们为了自己开发方便,一般直接使用 <String, Object>*/
       RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
       template.setConnectionFactory(factory);
       /* Json序列化配置*/
       Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
       ObjectMapper om = new ObjectMapper().setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY).activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
       jackson2JsonRedisSerializer.setObjectMapper(om);
       /* String 的序列化*/
       StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
       /* key采用String的序列化方式*/
       template.setKeySerializer(stringRedisSerializer);
       /* hash的key也采用String的序列化方式*/
       template.setHashKeySerializer(stringRedisSerializer);
       /* value序列化方式采用jackson*/
       template.setValueSerializer(jackson2JsonRedisSerializer);
       /* hash的value序列化方式采用jackson*/
       template.setHashValueSerializer(jackson2JsonRedisSerializer);
       template.afterPropertiesSet();
       return template;
  }
}

Redis.config

持久化

rdb

aof

发布订阅

SUBSCRIBE channel [channel ...]                         #监听频道发布的消息
PUBLISH channel message #发布一条消息到频道

主从复制

SLAVEOF host port       #指定当前服务器的主服务器
SLAVE NO ONE #设置自己为主机

 

主机:

127.0.0.1:6379> info replication  #复制信息
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=56,lag=1
slave1:ip=127.0.0.1,port=6380,state=online,offset=56,lag=1
master_replid:beb1baebd656aad26784b1a9a3ac5195ba48a6fc
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56

从机1:

127.0.0.1:6380> SLAVEOF 127.0.0.1 6379    
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6329
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:0
master_link_down_since_seconds:1593673454
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:0d5f7edff38ddbe00fdd966bb364cd95832bd754
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

从机2:

127.0.0.1:6381> SLAVEOF 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:1186
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:beb1baebd656aad26784b1a9a3ac5195ba48a6fc
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1186
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1186

哨兵

配置文件sentinel.conf

sentinel monitor redis6379 127.0.0.1 6379 1 # 设置被监视的主机  1代表主机宕机,从机进行投票又谁来接管当主机

启动哨兵模式

[root@iZj6ce9mxelwebmleutufgZ bin]# redis-sentinel liuyifan_config/sentinel.conf 
26718:X 03 Jul 2020 09:59:39.043 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
26718:X 03 Jul 2020 09:59:39.043 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=26718, just started
26718:X 03 Jul 2020 09:59:39.043 # Configuration loaded
              _._                                                  
          _.-``__ ''-._                                            
    _.-``    `. `_.  ''-._           Redis 5.0.8 (00000000/0) 64 bit
.-`` .-```. ```\/   _.,_ ''-._                                  
(    '     ,       .-` | `,   )     Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
|    `-._   `._   /     _.-'   |     PID: 26718
 `-._   `-._  `-./ _.-'   _.-'                                  
|`-._`-._    `-.__.-'   _.-'_.-'|                                  
|    `-._`-._       _.-'_.-'   |           http://redis.io        
 `-._   `-._`-.__.-'_.-'   _.-'                                  
|`-._`-._    `-.__.-'   _.-'_.-'|                                  
|    `-._`-._       _.-'_.-'   |                                  
 `-._   `-._`-.__.-'_.-'   _.-'                                  
     `-._   `-.__.-'   _.-'                                      
         `-._       _.-'                                          
             `-.__.-'                                              

26718:X 03 Jul 2020 09:59:39.045 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
26718:X 03 Jul 2020 09:59:39.047 # Sentinel ID is deebb6e0d6ec32dc04352897d646dc953e149ef0
26718:X 03 Jul 2020 09:59:39.047 # +monitor master redis6379 127.0.0.1 6379 quorum 1
26718:X 03 Jul 2020 10:10:51.505 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:11:01.542 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ redis6379 127.0.0.1 6379

当主机(6379)宕机后,哨兵实时情况,重新选举端口为6380的redis为主机

26718:X 03 Jul 2020 10:13:47.048 # +sdown master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.048 # +odown master redis6379 127.0.0.1 6379 #quorum 1/1
26718:X 03 Jul 2020 10:13:47.048 # +new-epoch 1
26718:X 03 Jul 2020 10:13:47.048 # +try-failover master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.051 # +vote-for-leader deebb6e0d6ec32dc04352897d646dc953e149ef0 1
26718:X 03 Jul 2020 10:13:47.051 # +elected-leader master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.051 # +failover-state-select-slave master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.141 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.141 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:47.225 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:48.117 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:48.117 # +failover-state-reconf-slaves master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:48.167 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:49.191 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:49.191 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:49.248 # +failover-end master redis6379 127.0.0.1 6379
26718:X 03 Jul 2020 10:13:49.248 # +switch-master redis6379 127.0.0.1 6379 127.0.0.1 6380
26718:X 03 Jul 2020 10:13:49.248 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ redis6379 127.0.0.1 6380
26718:X 03 Jul 2020 10:13:49.248 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ redis6379 127.0.0.1 6380

当原先宕机的主机(6379)重启后,不会重新作为原来的主机使用,而是变为从机

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:32106
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f6d18ec2f966daa15caaae9b5e40d8d3bd566daf
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:32106
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:24694
repl_backlog_histlen:7413
127.0.0.1:6379>

哨兵模式全部配置(转自狂神说Redis)

# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379(集群下的话 需要配置多个哨兵端口)
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),
#将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# shell编程
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已
#经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通
#信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
# 一般都是由运维来配置!

 转自 :狂神说java

关注公众号:狂神说,获取最新最全的全栈工程师教程

 

posted @ 2020-06-29 17:15  JasonLau01  阅读(174)  评论(0)    收藏  举报