目录
8、免费的 Redis 可视化工具 AnotherRedisDesktopManager
10、一个Redis 有16个库 编码为0-15,默认为0数据库
12、ShardedJedisPool 的一个推荐配置:分片
13、JedisSentinelPool 的一个推荐配置:哨兵
1、安装
可以从这里得到 linux版本和win版本的安装版和解压版的压缩包:点击下载
对于window来说,其下载于GitHub的开源release中的版本,有mis和zip两种,其实是一样的,在window中安装mis或者解压缩zip效果是一样的,只需要一个。
只能是64位的windows系统
也可以从官网下载,参考教程:Windows下安装并设置Redis (附属链接-java调用redis服务器 )
2、linux 安装
单机部署-https://www.jb51.net/article/116864.htm
-集群部署 https://www.cnblogs.com/kangoroo/p/7657616.html
linux可以有后台启动,这样在启动redis之后关闭对话框也可以继续访问。(http://www.tuicool.com/articles/aQbQ3u)
3、启动
对于windows平台,安装版的即 Redis-x64-3.2.100-win安装版-注册系统服务.msi,可以在 系统的 任务管理器/服务 下找到 Redis
对于windows平台解压版的,需要在cmd 进入dos窗口,然后cd Redis 解压目录,然后运行 redis-server.exe redis.windows.conf
客户端的话需要从新打开一个dos窗口,然后进入Redis的解压目录,运行 redis-cli.exe
安装版的也可以使用解压版的启动方式
服务端截图
客户端截图
4、MAC 平台下的安装和启动
安装可以看官网 Download | Redis,下载后运行下面的解压和编译命令
也可以用命令行(wget)下载
$ wget http://download.redis.io/releases/redis-5.0.7.tar.gz
$ tar xzf redis-5.0.7.tar.gz
$ cd redis-5.0.7
$ make
进入文件夹 redia-**/src
直接在命令行运行 redis-server 即可启动服务端
redis-cli 即启动客户端
4、报错
creating server tcp listening socket 127.0.0.1:6379: bind No error
这是因为redis-server 已经启动了,不需要再次启动,直接在redis-cli中测试调用即可
5、教程
http://os.51cto.com/art/201403/431103.htm
6、Redis原生命令学习
http://www.runoob.com/redis/redis-lists.html
7、关于 Redis 存储信息可以备份到硬件
有两个机制,一是自动的,在配置文件 redis.windows.conf 中可以看到下面的配置,当然是可以修改的
save 900 1
save 300 10
save 60 10000
save <seconds> <changes>
In the example below the behaviour will be to save:
# after 900 sec (15 min) if at least 1 key changed 每隔15分钟,当至少一个更改,则保存到硬盘一次
# after 300 sec (5 min) if at least 10 keys changed 每隔5分钟,当至少10个更改,则保存到硬盘一次
# after 60 sec if at least 10000 keys changed 每隔1分钟,当至少10000个更改,则保存到硬盘一次
你也可以直接在客户端运行 save,然后服务器端就可以单刀Redis有保存的动作了。
客户端-save
客户端
保存到硬盘的数据在Redis下次启动的时候会被自动加载。
重启Redis,自动从硬盘加载数据
8、免费的 Redis 可视化工具 AnotherRedisDesktopManager
> 这是一个开源的软件
AnotherRedisDesktopManager 发行版 - Gitee.com
mac 也可以直接在命令行运行:
(百度网盘:https://pan.baidu.com/s/1FzWpZtNWgwuHZDBhya4B4Q 密码: 9t4d)
低版本macOS brew cask install another-redis-desktop-manager
高版本macOS brew install android-platform-tools --cask
9、Redis 设置客户端连接密码
Redis 可以设置连接密码,可以直接在配置文件设置,页可以通过命令行设置
9.1、在配置文件中设置,设置完毕后需要重启redis
> redis.conf 文件
requirepass 密码值
9.2、通过命令行设置-无需重启
config set requirepass 密码值
9.3、密码验证方式-即登陆方式
auth 密码值
9.4、密码是明文存储的-注意网络隔离
> 通过下面的命令即可看到密码明文
config get requirepass
10、一个Redis 有16个库 编码为0-15,默认为0数据库
> 单机模式下,redis支持0-15共16个数据库,默认为0数据库,数据库之间相互隔离,可以使用select n命令进行数据库选择.
>集群模式下一个Redis只能使用一个数据库.
>集群模式下,至少3个主服务器,一般会给主服务器配置从服务器.
>Redis每一个数据库有 16384 个卡槽,集群模式下不同的主服务器负责一定区间的卡槽的存储.
>为什么是 16384? 集群数据库之间需要同步心跳数据,卡槽太多同步数据量就会过大,建议集群下不超过redis不超过1000个(https://blog.csdn.net/chenxuegui1234/article/details/100171599).
>为了防止主服务器挂掉,可以使用 哨兵机制,自动将从服务器升级为主服务器·一般是集群+哨兵联合使用,哨兵负责主备切换.
11、JedisPool 的一个推荐配置
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
/**数据库连接池*/
private static JedisPool jedisPool;
static {
JedisPoolConfig config = new JedisPoolConfig();
// 设置最大连接数,(根据并发请求合理设置)。
config.setMaxTotal(100);
// 设置最大空闲连接数,(根据并发请求合理设置)
config.setMaxIdle(20);
// 多长空闲时间之后回收空闲连接
config.setMinEvictableIdleTimeMillis(60000);
// 设置最小空闲连接数或者说初始化连接数
config.setMinIdle(10);
// 设置最大等待时间
config.setMaxWaitMillis(500);
// 跟验证有关
config.setTestOnBorrow(true);
// 跟验证有关
config.setTestOnReturn(true);
// 启动空闲连接的测试
config.setTestWhileIdle(false);
//config 是上面的配置对象
//127.0.0.1 是redis 服务器地址
//6379 是redis 服务器端口
// 30000 是连接超时时间
// 密码就是密码
//一个redis实例有0-15,共16个数据库,默认是0数据库
jedisPool = new JedisPool(config,"127.0.0.1",6379,30000,"密码",1);
}
public static void main(String[] args) {
Jedis jedis=jedisPool.getResource();
//1秒过期 ex 表示时间单位为秒
jedis.setex("name",1,"jecket");
//1秒过期,存在才添加,
//XX 表示key 已存在才可以,NX表示key不存在才可以
//ex时间单位为秒,px时间单位为毫秒
jedis.set("name","jecket","XX","ex",1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//键过期所以获取不到了
System.out.println(jedis.get("name"));
}
12、ShardedJedisPool 的一个推荐配置:分片
> 分片模式下 Hash一致 https://m.2cto.com/kf/201612/582310.html
import java.util.ArrayList;
import java.util.List;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.util.Hashing;
import redis.clients.util.Sharded;
public class ShardedJedisPoolTest {
/** Redis 集群 连接池对象 ShardedJedisPool*/
private static ShardedJedisPool shardedJedisPool;
static {
JedisPoolConfig config = new JedisPoolConfig();
// 设置最大连接数,(根据并发请求合理设置)。
config.setMaxTotal(100);
// 设置最大空闲连接数,(根据并发请求合理设置)
config.setMaxIdle(20);
// 多长空闲时间之后回收空闲连接
config.setMinEvictableIdleTimeMillis(60000);
// 设置最小空闲连接数或者说初始化连接数
config.setMinIdle(10);
// 设置最大等待时间
config.setMaxWaitMillis(500);
// 跟验证有关
config.setTestOnBorrow(true);
// 跟验证有关
config.setTestOnReturn(true);
// 启动空闲连接的测试
config.setTestWhileIdle(false);
//集群中 redis 机器列表
// host,端口,连接超时时间,读取数据超时时间,权重-默认为1
JedisShardInfo shardInfo1 = new JedisShardInfo("127.0.0.1", 6379, 3000,3000,1);
shardInfo1.setPassword("admin");
//将 redis 机器信息添加到 List 中
List<JedisShardInfo> list=new ArrayList<JedisShardInfo>();
list.add(shardInfo1);
//hash算法支持 支持MURMUR_HASH 和MD5两种算法,默认是Hashing.MURMUR_HASH
//还可以传入keyTagPattern来指定我们key的分布策略,所有能够匹配keyTagPattern的key
//(通过正则匹配)将放在同一个redis里,默认的是直接使用key来进行判定,默认Pattern DEFAULT_KEY_TAG_PATTERN = Pattern.compile("\\{(.+?)\\}")
shardedJedisPool=new ShardedJedisPool(config,list,Hashing.MURMUR_HASH,Sharded.DEFAULT_KEY_TAG_PATTERN);
}
public static void main(String[] args) {
//jdk1.7 之后的操作,在try内获取资源,会自动释放资源
try(ShardedJedis sharedJedis=shardedJedisPool.getResource()){
sharedJedis.set("name", "jecket");
System.out.println(sharedJedis.get("name"));
}
}
}
13、JedisSentinelPool 的一个推荐配置:哨兵
> 哨兵与集群是两个独立的功能,但从特性来看哨兵可以视为集群的子集,当不需要数据分片或者在客户端进行分片的场景下使用哨兵就足够了,但如果需要进行水平扩容,则集群是一个较好的选择。
14、redis 借助 lua 实现分布式锁
* 加锁时 key 同,value 不同。
* 释放锁时,根据value判断,是不是我的锁,不能释放别人的锁。
* 及时释放锁,而不是利用自动超时。
* 锁超时时间一定要结合业务情况权衡,过长,过短都不行。
* 程序异常之处,要捕获,并释放锁。如果需要回滚的,主动做回滚、补偿。保证整体的健壮性,一致性。
https://www.cnblogs.com/demingblog/p/9542124.html
package com.bestcxx.test;
import java.util.Collections;
import java.util.UUID;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 实现 Redis 分布式锁
*
* @author jie.wu
*/
public class RedisLock {
/** 锁释放成功标志 */
private static final Long LOCK_RELEASE_OK = 1L;
/** 最大锁超时时间 */
private static final int MAX_EXPIRED_NX = 10000;
/** 本类使用 static 代码块进行初始化操作 */
private static JedisPool jedisPool;
/**对象码*/
private String val;
/**
* 初始化 RedisPool
*/
static {
JedisPoolConfig config = new JedisPoolConfig();
// 设置最大连接数,(根据并发请求合理设置)。
config.setMaxTotal(100);
// 设置最大空闲连接数,(根据并发请求合理设置)
config.setMaxIdle(20);
// 多长空闲时间之后回收空闲连接
config.setMinEvictableIdleTimeMillis(60000);
// 设置最小空闲连接数或者说初始化连接数
config.setMinIdle(10);
// 设置最大等待时间
config.setMaxWaitMillis(500);
// 跟验证有关
config.setTestOnBorrow(true);
// 跟验证有关
config.setTestOnReturn(true);
// 启动空闲连接的测试
config.setTestWhileIdle(false);
// config 是上面的配置对象
// 127.0.0.1 是redis 服务器地址
// 6379 是redis 服务器端口
// 30000 是连接超时时间
// 密码就是密码
// 一个redis实例有0-15,共16个数据库,默认是0数据库
jedisPool = new JedisPool(config, "127.0.0.1", 6379, 30000);
//jedisPool = new JedisPool(config, "127.0.0.1", 6379, 30000,"密码",1);
}
public String getVal() {
return val;
}
/**
* 重写构造方法
*/
public RedisLock () {
this.val=UUID.randomUUID().toString();
}
/**
* 获取 JedisPool 资源
*
* @return
*/
public static JedisPool getJedisPool() {
if(jedisPool==null) {
try {
throw new Exception("系统异常");
} catch (Exception e) {
e.printStackTrace();
}
}
return jedisPool;
}
/**
* 指定 key \value \超时时间
*
* @param key
* @param lockValue
* @param expire
* @return
*/
public static boolean lock(String key, String lockValue, int expire) {
if (null == key) {
return false;
}
try {
Jedis jedis = getJedisPool().getResource();
String res = jedis.set(key, lockValue, "NX", "EX", expire);
jedis.close();
return res != null && res.equals("OK");
} catch (Exception e) {
return false;
}
}
/**
* 获取一个分布式锁 , 超时则返回失败
*
* @param key 锁的key
* @param lockValue 锁的value
* @param timeout 获取锁的等待时间,单位为 秒
* @return 获锁成功 - true | 获锁失败 - false
*/
public static boolean tryLock(String key, String lockValue, int timeout, int expire) {
final long start = System.currentTimeMillis();
if (timeout > MAX_EXPIRED_NX) {
timeout = MAX_EXPIRED_NX;
}
final long end = start + timeout * 1000;
boolean res = false; // 默认返回失败
while (!(res = lock(key, lockValue, expire))) { // 调用了上面的 lock方法
if (System.currentTimeMillis() > end) {
break;
}
}
return res;
}
/**
* 强制释放锁
*
* @param key
* @param lockValue
* @return
*/
public static boolean releaseLock(String key, String lockValue) {
if (key == null || lockValue == null) {
return false;
}
try {
Jedis jedis = RedisLock.getJedisPool().getResource();
Object res = jedis.eval("if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end", Collections.singletonList(key), Collections.singletonList(lockValue));
jedis.close();
return res != null && res.equals(LOCK_RELEASE_OK);
} catch (Exception e) {
return false;
}
}
private static final String key="redislock_test";
/**
* 打包一个调用分布式锁到测试方法
* @param str
*/
public static void testMethod(String str) {
RedisLock r=new RedisLock();
try{
if(r.tryLock(key, r.getVal(), 1, 60*1000)) {
System.out.println(str+":获得锁了");
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
System.out.println(str+":没获取到锁");
}
}finally {
r.releaseLock(key, r.getVal());
System.out.println(str+":解锁");
}
}
public static void main(String[] args) {
Thread t1=new Thread("t1") {
@Override
public void run() {
super.run();
testMethod(Thread.currentThread().getName());
}
};
Thread t2=new Thread("t2") {
@Override
public void run() {
super.run();
testMethod(Thread.currentThread().getName());
}
};
Thread t3=new Thread("t3") {
@Override
public void run() {
super.run();
testMethod(Thread.currentThread().getName());
}
};
t1.start();
t2.start();
t3.start();
}
}
15、Redis 在 Java 中操作的三种工具
本段内容转自 Redis的三个框架:Jedis,Redisson,Lettuce
Jedis api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html
redisson 官网地址:https://redisson.org/
redisson git项目地址:https://github.com/redisson/redisson
lettuce 官网地址:https://lettuce.io/
lettuce git项目地址:https://github.com/lettuce-io/lettuce-core
概念:
Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,
Redisson:实现了分布式和可扩展的Java数据结构。
Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。
优点:
Jedis:比较全面的提供了Redis的操作特性
Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列
Lettuce:主要在一些分布式缓存框架上使用比较多
可伸缩:
Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。
Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作
Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作
结论:
建议使用:Jedis + Redisson
16、参考
https://my.oschina.net/xinxingegeya/blog/391713 https://www.cnblogs.com/vhua/p/redis_1.html
redis 支持主从和分片 https://www.cnblogs.com/xiaoblog/p/5776892.html
https://blog.csdn.net/Richardlygo/article/details/82119938
https://blog.csdn.net/wzy0623/article/details/82706614