Redis 学习一则
2019-3-28
Redis
Redis 简介
Redis 是完全开源免费的, 遵守BSD协议, 是一个高性能的key-value内存数据库;
Redis 与其他 key - value 缓存产品有以下三个特点:
Redis支持数据的持久化, 可以将内存中的数据保存在磁盘中, 重启的时候可以再次加载进行使用;
Redis不仅仅支持简单的key-value类型的数据, 同时还提供list, set, zset, hash等数据结构的存储;
Redis支持数据的备份, 即master-slave模式的数据备份;
还有一点它是单线程的
官页
官页 - 全命令列表
github官页
菜鸟教程
redis 中文文档
安装
源码安装for linux
解压
make
make install
OK
which redis
make install默认安装目录是/usr/local/...
安装 for windowns
-
git下载 Redis-x64-xx.zip
-
解压
-
启动
cmd到目录 运行:redis-server.exe redis.windows.conf -
客户端
cmd到目录 运行:
redis-cli.exe -h 127.0.0.1 -p 6379
集群配置
密码与验证
配置
redis.conf文件
# requirepass abc123.com //配置密码
密码
默认情况下 requirepass 参数是空的, 这就意味着你无需通过密码验证就可以连接到 redis 服务;
你可以通过以下命令来修改该参数:
127.0.0.1:6379> CONFIG set requirepass "runoob"
OK
127.0.0.1:6379> CONFIG get requirepass
- "requirepass"
- "runoob"
验证
127.0.0.1:6379> AUTH password
实例
127.0.0.1:6379> AUTH "runoob"
OK
127.0.0.1:6379> SET mykey "Test value"
OK
127.0.0.1:6379> GET mykey
"Test value"
6.0 以后的验证用户名
在6.0以前验证是不需要用户名, 那么在升级6.0之后的用户名是什么?
AUTH <username> <password>
What happens is that the username used to authenticate is "default", so just specifying the password implies that we want to authenticate against the default user. This provides backward compatibility.
"default" 是默认用户名
启动/关闭
启动
./redis-server redis.conf
关闭
- 单机关闭
-
先连接上
./redis-cli -
shutdown 命令
shutdown
- 集群/批量关闭
写个shell 批处理
redis01/redis-cli -p 6379 shutdown
redis02/redis-cli -p 6380 shutdown
Redis Select 命令(换索引库)
Redis Select 命令用于切换到指定的数据库, 数据库索引号 index 用数字值指定, 以 0 作为起始索引值;
语法
redis 127.0.0.1:6379> SELECT index
Redis keys 命令
DEL key
该命令用于在 key 存在时删除 key;
DUMP key
序列化给定 key , 并返回被序列化的值;
EXISTS key
检查给定 key 是否存在;
EXPIRE key seconds
为给定 key 设置过期时间, 以秒计;
KEYS pattern
查找所有符合给定模式( pattern)的 key ;
PERSIST key
移除 key 的过期时间, key 将持久保持
TTL key
以秒为单位, 返回给定 key 的剩余生存时间(TTL, time to live);
TYPE key
返回 key 所储存的值的类型;
Redis 字符串操作 命令
SET key value
设置指定 key 的值
GET key
获取指定 key 的值;
GETRANGE key start end
返回 key 中字符串值的子字符
GETSET key value
将给定 key 的值设为 value , 并返回 key 的旧值(old value);
Redis Incr 命令 (自增)
- Redis Incr 命令将 key 中储存的数字值增一;
2.如果 key 不存在, 那么 key 的值会先被初始化为 0 , 然后再执行 INCR 操作; - 本操作的值限制在 64 位(bit)有符号数字表示之内;
- 如果值包含错误的类型, 或字符串类型的值不能表示为数字, 那么返回一个错误;
- 对应的自减命令是
DECR key
依据这个特性可以非常容易完成 生成流水号之类的业务
public String getSeriesCode(String terninalCode) {
Assert.hasLength(terninalCode, "终端号不能未空!");
StringJoiner series = new StringJoiner("-");
series.add("SSDWA");
series.add(terninalCode);
//
LocalDate dateNow = LocalDate.now();
final String dateFmtValue = dateNow.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
final String forKey = "jyQuarantineManualAA::SSDWA:"+dateFmtValue;//key
series.add(dateFmtValue);
if (!redisTemplate.hasKey(forKey)) {
//先设一下, 过期时间
redisTemplate.opsForValue().set((Object)forKey, (Object)0, Duration.ofHours(25));
}
//自增
Long increaseValue = redisTemplate.opsForValue().increment(forKey);
String str = increaseValue.toString();
// 补零
String code="";
for (int i = str.length(); i < 5; i++) {
code+="0";
}
series.add(code + str);
return series.toString();
}
public String getSeriesCode(String orgCode, boolean isIncrement) {
LocalDate dateNow = LocalDate.now();
final String dateFmtValue = dateNow.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
final String forKey = "ServiceTask:"+orgCode+":"+dateFmtValue;//key
if (!redisTemplate.hasKey(forKey)) {
//先设一下, 过期时间
redisTemplate.opsForValue().set((Object)forKey, (Object)0, Duration.ofHours(25));
}
//自增
Long increaseValue = 1L;
if (isIncrement){
increaseValue = redisTemplate.opsForValue().increment(forKey);
}else{
Integer val = (Integer)redisTemplate.opsForValue().get(forKey);
increaseValue = val+1L;
}
String str = increaseValue.toString();
// 补零
String code="";
for (int i = str.length(); i < 4; i++) {
code+="0";
}
StringJoiner series = new StringJoiner("");
series.add(dateFmtValue);
series.add(code + str);
return series.toString();
}
Redis 事务
//监控key
redisTemplate.watch(KEY_DEF);
//开始事务
redisTemplate.multi();
//do something..
//放弃事务
//redisTemplate.discard();
//执行事务
List<Object> rs = redisTemplate.exec(); //如果没有问题, 最终将会返回List: [true,"value",true,"value"……], 如果WATCH的键值被修改, 将会返回空list, 但是不会报错;
必须要结合WATCH 监控, 才能完成事务逻辑, (watch 和 multi 后, 对 KEY_DEF 的修改会导致 exec 执行失败)
当使用EXEC 执行事务时, 首先会比对WATCH所监控的键值对, 如果没发生改变, 它会执行事务队列中的命令, 提交事务; 如果发生变化, 将不会执行事务中的任何命令, 同时事务回滚; 当然无论是否回滚, Redis都会取消执行事务前的WATCH命令;
MULTI: 开启事务, redis会将后续的命令逐个放入队列中, 然后使用EXEC命令来原子化执行这个命令系列;
EXEC: 执行事务中的所有操作命令;
DISCARD: 取消事务, 放弃执行事务块中的所有命令;
WATCH key [key ...]监视一个(或多个) key , 如果在事务执行之前这个(或这些) key 被其他命令所改动, 那么事务将被打断;
UNWATCH: 取消WATCH对所有key的监视;
注意在 RedisTemplate 中默认是不支持事务的, 如有绑定连接会话的形式实现!
Long ret = redisTemplate.execute(new SessionCallback<Long>() {
@Override
public Long execute(RedisOperations operations) throws DataAccessException {
Long retValue ;
List rs = null;
do {
final String key = getCacheKey(type, userId);
operations.watch(key);
operations.multi();
JyQuarantinePStockCacheDTO value = syncGetCache(type, userId);
if(value == null ) {
throw new RuntimeException("没有可用的检疫证号!");
}
long curno = value.getCurno();
retValue = curno + 1;
value.setCurno(retValue );
if( retValue > value.getEndno() ) {
operations.discard();
operations.unwatch();
throw new RuntimeException("检疫证号已用完!");
}
operations.opsForValue().set(key, value);
rs = operations.exec();
} while (CollUtil.isEmpty(rs));
return retValue;
}
});
return ret;
Redis 脚本
redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
执行 Lua 脚本;
redis 127.0.0.1:6379> EVALSHA sha1 numkeys key [key ...] arg [arg ...]
执行 Lua 脚本;
SCRIPT KILL
杀死当前正在运行的 Lua 脚本;
批量删除 匹配keys
lua 脚本, 删除模糊匹配的key
./redis-cli eval "redis.call('del', unpack(redis.call('keys','dept::*')))" 0
./redis-cli eval "redis.call('del', unpack(redis.call('keys','user::loadUserByUsername')))" 0
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 'user::loadUserByUsername*'
基于SET 指令分布式同步锁
SET
SET key value[EX seconds][PX milliseconds][NX|XX]
NX :表示key不存在的时候,才能set成功,保证第一个请求才能获得锁,而其他客户端请求只能等其释放锁,才能获取。
EX seconds :设定key的过期时间,时间单位是秒。
PX milliseconds: 设定key的过期时间,单位为毫秒
XX: 仅当key存在时设置值
以下指令设置 locak_value, 过期时间10 秒
SET locak_value true ex 10 nx
备份/恢复
//该命令将在 redis 安装目录中创建dump.rdb文件;
redis 127.0.0.1:6379> SAVE
//也可以使用命令 BGSAVE, 该命令在后台执行
127.0.0.1:6379> BGSAVE
//只需将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可; 获取 redis 目录可以使用 CONFIG 命令
redis 127.0.0.1:6379> CONFIG GET dir
with spring boot (JSR-107)
参考 boot 文档: 32. Working with NoSQL Technologies
配置
依赖 spring-boot-starter-data-redis Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client
POM
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.properties
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=300
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000
RedisTemplate 操作
ValueOperations: 简单K-V操作
SetOperations: set类型数据操作
ZSetOperations: zset类型数据操作
HashOperations: 针对map类型的数据操作
ListOperations: 针对list类型的数据操作
提供了对key的"bound"(绑定)便捷化操作API, 可以通过bound封装指定的key,
然后进行一系列的操作而无须"显式"的再次指定Key, 即BoundKeyOperations:
BoundValueOperations
BoundSetOperations
BoundListOperations
BoundSetOperations
BoundHashOperations
https://www.cnblogs.com/superfj/p/9232482.html
https://mp.weixin.qq.com/s/FGjbASnUguPaQw30Omymow

浙公网安备 33010602011771号