string
字符串可以保存三种类型数据:
字符串、整数、浮点数
list
一个列表结构可以有序的存储多个字符串.
指令:[LPOP/RPOP 集合名] 从列表的左/右弹出一个值,并返回被弹出的值(被弹出的值,不存在于列表中)
brpop类似blpop
-rpoplpush source-key dest-key 从source-key弹出最右侧元素推入dest-key的最左侧元素
-brpoplpush 可阻塞的 rpoplpush
set
和Java的set相同,唯一无序.
一些简单的命令:SINTER、SUNION、SDIFF 交集计算、并集计算和差集计算等等指令
hashmap
可以存储多个键值对之间的映射.
散列存储的值既可以是字符串也可以是数字.
用户同样可以对散列存储的数字执行自增或自减操作
指令:
zset
特点:命令:
事务
通过watch、multi和exec可以制作一个事务流水线. 减少应用和redis的交互,提高性能.
watch会监控键,如果在执行exec之前表新增、修改、删除的话,那么exec的时候就会返回错误信息,可以重试交易
watch
redis的cas操作.
在watch期间监视的值发生变动,事务失败:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
multi
原子执行事务的开始点
exec
原子执行事务的结束点
不支持回滚
流水线
使用conn.pipelined()
如果有true这个参数就是使用事务,不写或者false参数就是单纯的流水线.性能会进一步得到提高
过期
数据会丢失
数据传输的可靠性,如果客户端在执行订阅操作的过程中断线,断线期间发送的消息会丢失
如果能承担一部分数据的丢失可以使用.
snapshotting
保存某一时间点的所有信息.
适用场景: 快照要时没照完系统就崩溃了,就会丢失最后一次成功快照后的信息,所以在能承受丢失部分信息的时候,才使用这个.
不适用场景: 很大的数据占用很大的内存,创建子进程会造成很长的停顿时间.有些应用无法接受
灵活: 可在dbfilename文件配置输出的文件名,还可配置输出目录
相关指令:
bgsave Redis创建一个子进程后台保存快照.
save 拒绝接受请求,专一的执行快照,所以这个不常用
在配置文件设置 save 60 10000 表示在60秒内有10000个写操作的时候,保存数据,如果有多个配置,满足一个就执行
shutdown 或标准的term指令,停止接受新命令,执行save命令,然后关闭redis
一个Redis对另一个Redis 服务器发起SYNC命令,如果没在执行BGSAVE就执行BGSAVE
- 数据丢失
- 影响redis性能
- 系统故障,数据无法修复
只追加文件
将修改数据库的命令写入 只追加(append-only)文件里面. 只追加写入设置可以设置为
从不同步、每秒同步一次或每写入一个命令就同步一次
Redis提供主从复制功能
append only file
持久化的数据追加到之前的文件的末尾.
三个同步指令:
appendfsync always 同步每个指令,频繁的写指令系统会崩溃
appendfsync everysec 最多丢失一秒的数据
appendfsync no 会丢失不可控的数据,过多的写操作还会降低redis的存储速度
缺点: 持久化后的文件太大了
可对文件进行压缩
压缩需要使用子进程,Redis过大创建子进程的时间会更多,问题和之前相同.
可以灵活的设置压缩文件的指令,超过某大小或超过上一次压缩的大小的几倍,就可以执行压缩命令,提供后台压缩命令
redis-benchmark -c l -q
-c l 使用单机测试
-q 简化测试
注意: 实际的生产环境性能只有测试效果的50%-60%,因为测试不会处理返回结果
主从复制
使用流
分片
redis集群中有16384个散列槽.
集群至少拥有三个节点:
节点A包含从0到5500的散列槽。
节点B包含从5501到11000的散列槽。
节点C包含从11001到16383的散列槽
新增节点,从三个节点分出一部分数据给D
删除节点把节点的数据平均移动给其他节点
主从复制
每个主节点,必须有一个从节点,保证数据高可用.主节点崩溃,从节点替换,从节点上升为主节点.主节点恢复后变为从节点
弱一致性
需要在性能和一致性之间进行权衡。
为性能牺牲一致性
集群总线端口
同一个客户端,不同配置文件
使用相同的内存
手动故障转移
Redis Cluster使用CLUSTER FAILOVER 命令支持手动故障转移,该命令必须在要故障转移的主站的一个从站中执行。
副本迁移
在Redis群集中,只需使用以下命令,就可以随时使用不同的主服务器重新配置从属服务器进行复制:
CLUSTER REPLICATE
增加/删除新节点
新增节点:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
准确指定要使用新副本定位的主控制器:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave --cluster-master-id xxxxx
要删除从节点,只需使用del-noderedis-cli命令:
redis-cli --cluster reshard 127.0.0.1:7000
写上所有插槽的数量
写上转移的id
写上自己的id
done
redis-cli --cluster del-node 127.0.0.1:7000 <node-id>
无法使用multi
[] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: MULTI is currently not supported in cluster mode.] with root cause
监控
Sentinel会不断检查主实例和从属实例是否按预期工作。
通知
Sentinel可以通过API通知系统管理员,另一台计算机程序,其中一个受监控的Redis实例出现问题。
自动故障转移
如果主服务器未按预期工作,Sentinel可以启动故障转移过程,其中从服务器升级为主服务器,其他其他服务器重新配置为使用新主服务器,并且使用Redis服务器的应用程序通知有关新服务器的地址连接。
配置提供
Sentinel充当客户端服务发现的权限来源:客户端连接到Sentinels,以便询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,Sentinels将报告新地址。
修改sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
第一行用于告诉Redis监视一个名为mymaster的主服务器,它位于地址127.0.0.1和端口6379,仲裁数为2.
仲裁数用于检测故障的哨兵数量.最终选举一个sentinel进行故障转移
sentinel down-after-milliseconds mymaster 60000
down-after-milliseconds 对于Sentinel开始认为它已关闭的时间,实例不应该可以到达的时间(无论是不回复我们的PING还是回复错误)都是以毫秒为单位的时间。
sentinel failover-timeout mymaster 180000
失效转移超时时间,投票后的哨兵进行故障转移其他哨兵在此时间后可进行重试的时间
sentinel parallel-syncs mymaster 1
同步数据给从服务器的数量,这个数越大,同步数据的时间越少但是不可用的服务器越多.数量越少同步时间越多,但是可用的服务器越多.
应该将此选项设置为值1来确保一次只能访问一个从站。
使用方式
始终在三个不同的服务器中至少部署三个Sentinels
测试结果:
服务器A拥有主服务M1和哨兵S1,
服务器B拥有从服务R1和哨兵S2.
在M1崩溃时可以进行故障转移,但是如果服务器A整体崩溃,只有一个哨兵S2则无法进行故障转移.
增加服务器C哨兵S3. 在服务器A整体崩溃后,也可进行故障转移
解决从服务器丢失数据问题
Redis实例作为主服务器时,如果无法写入至少1个从服务器,将停止接受写入。由于复制是异步的,因此无法实际写入意味着从属设备已断开连接,或者未向我们发送超过指定max-lag秒数的异步确认。
Redisson是一个Redis的Java客户端,Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
可重入锁(Reentrant Lock)
基于Redis的Redisson分布式可重入锁RLock Java 对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
RLock lock = redisson.getLock("anyLock");
// 最常见的使用方法
lock.lock();
自动解锁的方式:
// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
...
} finally {
lock.unlock();
}
}
公平锁(Fair Lock)
基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
RLock fairLock = redisson.getFairLock("anyLock");
// 最常见的使用方法
fairLock.lock();
联锁(MultiLock)
基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();
红锁(RedLock)
基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。
红锁是一个钟更安全的锁.
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();
独享
独享(相互排斥)。在任意一个时刻,只有一个客户端持有锁。
无死锁
无死锁。即便持有锁的客户端崩溃(crashed)或者网络被分裂(gets partitioned),锁仍然可以被获取。
容错
容错。 只要大部分Redis节点都活着,客户端就可以获取和释放锁.
读写锁(ReadWriteLock)
基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
信号量(Semaphore)
基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
//或
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();
//或
semaphore.tryAcquireAsync();
semaphore.tryAcquire(23, TimeUnit.SECONDS);
//或
semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
semaphore.release(10);
semaphore.release();
//或
semaphore.releaseAsync();
可过期性信号量(PermitExpirableSemaphore)
基于Redis的Redisson可过期性信号量(PermitExpirableSemaphore)是在RSemaphore对象的基础上,为每个信号增加了一个过期时间。每个信号可以通过独立的ID来辨识,释放时只能通过提交这个ID才能释放
RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
String permitId = semaphore.acquire();
// 获取一个信号,有效期只有2秒钟。
String permitId = semaphore.acquire(2, TimeUnit.SECONDS);
// ...
semaphore.release(permitId);
闭锁(CountDownLatch)
基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
原文:https://www.cnblogs.com/xisuo/p/10936722.html