redis的学习(四)
13. 渐进式遍历
通过渐进式遍历能够获取当前所有的key,又不会讲当前的服务器卡死。不是一个命令将所有的key获取,而是每执行一次命令,只获取到其中的一部分。所以想要获取到所有的key就需要多次遍历,即化整为零的思想。
渐进式遍历其实是一组命令,其命令的使用方法是一样的。代表命令式scan。
化整为零的渐进式遍历:
count这里的数值不一定每一次都是一样的,渐进式遍历在遍历过程中,不会在服务器中存储任何的状态信息,且此处的遍历是随时可以终止的,不会对服务器产生任何的副作用。
渐进性遍历scan虽然解决了阻塞的问题,但如果在遍历期间键有所变化(增加、修改、删 除),可能导致遍历时键的重复遍历或者遗漏。在遍历的时候进行修改/新增/删除,会导致迭代器失效。
14. 数据库管理
redis中的database是现成的,用户不能创建新的,也不能删除已有的数据库。redis默认提供了16个数据库0~15,这些数据库中的数据是隔离的,默认使用的数据库是0号。
select dbIndex,切换数据库。
dbsize:获取当前库中存在的key的个数。
15. redis客户端介绍
工作中,是使用redis的api,来实现定制化的redis客户端程序,进一步操作redis服务器。即使用程序来操作服务器。
关于编写一个自定义的redis客户端:
主要是因为能够从redis官网获取redis服务器应用层的协议如下:
resp协议:
优点:1、简单好实现;2、快速进行解析;3、肉眼可读。
传输层这里基于tcp,但是和tcp没有进行强耦合。请求和响应之间是一问一答的模式机制。
simple string只能用来传输简单的文本,bulk string可以传输二进制数据。因此redis客户端服务器的工作就是:1、按照上述的格式,构造出字符串,往socket中写入。2、从socket中读取字符串,按照上述格式进行解析。
java生态中,开发代码高度依赖windows(idea),所以需要通过云服务器的外网ip来访问到linux服务器。redis在云服务器上的端口是6379,一般是被云服务器的防火墙保护起来的。redis的端口不能直接在防火墙上放开。
不能开发redis端口,邮箱能够通过外网访问方案:
1、直接让java程序也在linux上运行,即将java代码打包成可执行的jar包,然后将jar包拷贝到linux服务器上执行。
2、配置ssh端口转发,把云服务器的redis端口映射到本地主机。
下面描述云服务器的端口映射到本地主机:
windows(本地主机)的终端(类似于xsehll)通过ssh协议访问到云服务器。ssh既是协议也是程序,默认走22端口。ssh其中一个功能是能够支持端口转发,通过走ssh的22端口来传递去其他端口的数据信息。
即使用本地主机访问云服务器的6379端口,本地先构造一个ssh数据报,将访问redis的请求放到数据报里面,这个数据报会通过22端口发往服务器,服务器的ssh服务器程序就能解析出上述的数据报,将其交给6379端口的程序。一个linux主机上,存在很多的服务器,ssh肯呢个需要给多个端口传递数据,此时为了区分不同的端口,往往会把服务器的端口在本地用另外一个端口来表示。
所以把服务器的6379端口使用ssh进行端口映射,映射到本地8888端口。则本地的客户端程序访问127.0.0.1:8888,就相当于访问云服务器上的6379。
下图ssh端口转发隧道:
当ssh连接上之后端口转发才有效,把ssh连接断开之后,端口转发自然就消失了。 连接完成之后使用netstat命令来查看本地的8888端口监听情况。
15.1 创建java项目
1、使用jedis来操作redis
引入依赖:
</dependency> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.3.2</version> </dependency>
public class RedisDemo {
public static void main(String[] args) {
//连接redis服务器
JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");
// 后续记得cloas,只是放回到池里,并不是直接关闭tcp连接
try(Jedis jedis = jedisPool.getResource()){
String pong = jedis.ping();
System.out.println(pong);
}
}
}
运行结果如下:
程序运行成功除了ssh映射配置成功之外,还有就是最开始安装redis服务器的时候要配置绑定的ip以及关闭保护模式。
15.2 get和set
public class RedisDemo {
public static void main(String[] args) {
//连接redis服务器
JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");
// 后续记得cloas,只是放回到池里,并不是直接关闭tcp连接
try(Jedis jedis = jedisPool.getResource()){
// String pong = jedis.ping();
// System.out.println(pong);
test1(jedis);
}
}
public static void test1(Jedis jedis){
System.out.println("get和set的使用");
//清空数据库
// jedis.flushAll();
jedis.set("k11","11");
jedis.set("k12","12");
String value = jedis.get("k11");
System.out.println("value="+value);
}
}
运行结果:
15.2 exists 和 del
del可以删除多个key,以变⻓参数列表的⽅式体现.返回值是实际删除的key的个数.
boolean ret = jedis.exists("key1");
System.out.println(ret);
n = jedis.del("key2", "key3");
System.out.println(n);
15.3 keys的使用
public static void test3(Jedis jedis) {
jedis.set("key1", "value1");
jedis.set("key2", "value2");
jedis.set("key3", "value3");
jedis.set("myKey", "value4");
Set<String> keys = jedis.keys("*");
System.out.println(keys);
}
运行结果如下:
15.4 expire和ttl
public static void test4(Jedis jedis) {
System.out.println("expire和ttl的使用");
jedis.set("key1", "value1");
String type = jedis.type("key")
jedis.expire("k1",10);
long time = jedis.ttl("key1");
}
15.5 type
private static void testType(Jedis jedis) {
jedis.set("key1", "value");
System.out.println(jedis.type("key1"));
jedis.lpush("key2", "a", "b", "c");
System.out.println(jedis.type("key2"));
jedis.hset("key3", "name", "zhangsan");
System.out.println(jedis.type("key3"));
jedis.sadd("key4", "111", "222", "333");
System.out.println(jedis.type("key4"));
jedis.zadd("key5", 1, "aaa");
System.out.println(jedis.type("key5"));
}
15.6 string相关的命令
System.out.println("mget 和 mset");
jedis.flushAll();
jedis.mset("key1", "111", "key2", "222", "key3", "333");
List<String> values = jedis.mget("key1", "key2", "key100", "key3");
//返回的结果只和传递的参数有关,没有也会返回null
System.out.println("values: " + values);
System.out.println("getrange 和 setrange");
jedis.flushAll();
jedis.set("key", "abcdefghijk");
String result = jedis.getrange("key", 2, 5);
System.out.println("result: " + result);
jedis.setrange("key", 2, "xyz");
String value = jedis.get("key");
System.out.println("value: " + value);
System.out.println("append");
jedis.flushAll();
jedis.set("key", "abcdef");
jedis.append("key", "ghij");
String value = jedis.get("key");
System.out.println("value: " + value);
System.out.println("incr 和 decr");
jedis.flushAll();
jedis.set("key", "100");
long result = jedis.incr("key");
System.out.println("result: " + result);
result = jedis.decr("key");
System.out.println("result: " + result);
value = jedis.get("key");
System.out.println("value: " + value);
15.7 list相关的命令
System.out.println("lpush 和 lrange");
jedis.flushAll();
jedis.lpush("key", "111", "222", "333");
List<String> result = jedis.lrange("key", 0, -1);
System.out.println(result);
System.out.println("rpush");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
List<String> result = jedis.lrange("key", 0, -1);
System.out.println("result: " + result);
System.out.println("lpop");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
String result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);
System.out.println("blpop");
jedis.flushAll();
// 返回结果是一个 "二元组", 一个是从哪个 key 对应的list中删除的, 一个是删除的元素是什么.
List<String> results = jedis.blpop(100, "key");
System.out.println("results[0]: " + results.get(0));
System.out.println("results[1]: " + results.get(1));
System.out.println("llen");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
long len = jedis.llen("key");
System.out.println("len: " + len);
15.8 关于set相关的命令
System.out.println("sadd 和 smembers");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333");
Set<String> result = jedis.smembers("key");
System.out.println("result: " + result);
System.out.println("sismember");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333");
boolean result = jedis.sismember("key", "100");
System.out.println("result: " + result);
System.out.println("scard");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333");
long result = jedis.scard("key");
System.out.println("result: " + result);
System.out.println("spop");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333", "444", "555");
String result = jedis.spop("key");
System.out.println("result: " + result);
System.out.println("sinter");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333");
jedis.sadd("key2", "111", "222", "444");
Set<String> result = jedis.sinter("key", "key2");
System.out.println("result: " + result);
System.out.println("sinterstore");
jedis.flushAll();
jedis.sadd("key", "111", "222", "333");
jedis.sadd("key2", "111", "222", "444");
long len = jedis.sinterstore("key3", "key", "key2");
System.out.println("len: " + len);
Set<String> result = jedis.smembers("key3");
System.out.println("result: " + result);
15.9 关于hash的指令
System.out.println("hset 和 hget");
jedis.flushAll();
jedis.hset("key", "f1", "111");
Map<String, String> fields = new HashMap<>();
fields.put("f2", "222");
fields.put("f3", "333");
jedis.hset("key", fields);
String result = jedis.hget("key", "f1");
System.out.println("result: " + result);
result = jedis.hget("key", "f2");
System.out.println("result: " + result);
result = jedis.hget("key", "f100");
System.out.println("result: " + result);
System.out.println("hexists");
jedis.flushAll();
jedis.hset("key", "f1", "111");
jedis.hset("key", "f2", "111");
jedis.hset("key", "f3", "111");
boolean result = jedis.hexists("key", "f1");
System.out.println("result: " + result);
result = jedis.hexists("key", "f100");
System.out.println("result: " + result);
System.out.println("hdel");
jedis.flushAll();
jedis.hset("key", "f1", "111");
jedis.hset("key", "f2", "111");
jedis.hset("key", "f3", "111");
long result = jedis.hdel("key", "f1", "f2");
System.out.println("result: " + result);
boolean exists = jedis.hexists("key", "f1");
System.out.println("exists: " + exists);
exists = jedis.hexists("key", "f2");
System.out.println("exists: " + exists);
System.out.println("hkeys 和 hvals");
jedis.flushAll();
jedis.hset("key", "f1", "111");
jedis.hset("key", "f2", "111");
jedis.hset("key", "f3", "111");
Set<String> fields = jedis.hkeys("key");
List<String> vals = jedis.hvals("key");
System.out.println("fields: " + fields);
System.out.println("vals: " + vals);
System.out.println("hmget 和 hmset");
jedis.flushAll();
Map<String, String> map = new HashMap<>();
map.put("f1", "111");
map.put("f2", "222");
map.put("f3", "333");
jedis.hmset("key", map);
List<String> values = jedis.hmget("key", "f2", "f1", "f3");
System.out.println("values: " + values);
15.10 关于zset的指令
System.out.println("zadd 和 zrange");
jedis.flushAll();
jedis.zadd("key", 10, "zhangsan");
Map<String, Double> map = new HashMap<>();
map.put("lisi", 20.0);
map.put("wangwu", 30.0);
jedis.zadd("key", map);
List<String> members = jedis.zrange("key", 0, -1);
System.out.println("members: " + members);
List<Tuple> membersWithScore = jedis.zrangeWithScores("key", 0, -1);
System.out.println("membersWithScore: " + membersWithScore);
String member = membersWithScore.get(0).getElement();
double score = membersWithScore.get(0).getScore();
System.out.println("member: " + member + ", score: " + score);
System.out.println("zcard");
jedis.flushAll();
jedis.zadd("key", 10, "zhangsan");
jedis.zadd("key", 20, "lisi");
jedis.zadd("key", 30, "wangwu");
long len = jedis.zcard("key");
System.out.println("len: " + len);
System.out.println("zrem");
jedis.flushAll();
jedis.zadd("key", 10, "zhangsan");
jedis.zadd("key", 20, "lisi");
jedis.zadd("key", 30, "wangwu");
long n = jedis.zrem("key", "zhangsan", "lisi");
System.out.println("n: " + n);
List<Tuple> result = jedis.zrangeWithScores("key", 0, -1);
System.out.println("result: " + result);
System.out.println("zscore");
jedis.flushAll();
jedis.zadd("key", 10, "zhangsan");
jedis.zadd("key", 20, "lisi");
jedis.zadd("key", 30, "wangwu");
Double score = jedis.zscore("key", "zhangsan2");
System.out.println("score: " + score);
System.out.println("zrank");
jedis.flushAll();
jedis.zadd("key", 10, "zhangsan");
jedis.zadd("key", 20, "lisi");
jedis.zadd("key", 30, "wangwu");
Long rank = jedis.zrank("key", "zhangsan2");
System.out.println("rank: " + rank);
jedis库的本质就是针对各种redis指令进行了包装,调用某个方法,就相当于在redis客户端中输入对应的命令。
2、在spring中操作redis
配置.yml文件,添加相关依赖。
// 后续 redis 测试的各种方法, 都通过这个 Controller 提供的 http 接口来触发.
@RestController
public class MyController {
@Autowired
private StringRedisTemplate redisTemplate;
//这里spring中是通过stringredisTemplate来操作redis
//stringredisTemplate是redisTemplate的子类,专门来处理文本数据
@GetMapping("/testString")
@ResponseBody
public String testString() {
redisTemplate.execute((RedisConnection connection) -> {
// execute 要求回调方法中必须写 return 语句. 返回个东西.
// 这个回调返回的对象, 就会作为 execute 本身的返回值.
connection.flushAll();
return null;
});
redisTemplate.opsForValue().set("key", "111");
redisTemplate.opsForValue().set("key2", "222");
redisTemplate.opsForValue().set("key3", "333");
String value = redisTemplate.opsForValue().get("key");
System.out.println("value: " + value);
return "OK";
}
@GetMapping("/testList")
@ResponseBody
public String testList() {
// 先清除之前的数据.
//使用lambda表达式来写函数式接口
redisTemplate.execute((RedisConnection connection) -> {
// execute 要求回调方法中必须写 return 语句. 返回个东西.
// 这个回调返回的对象, 就会作为 execute 本身的返回值.
//RedisConnection,代表了redis连接,对标jedis
connection.flushAll();
return null;
});
redisTemplate.opsForList().leftPush("key", "111");
redisTemplate.opsForList().leftPush("key", "222");
redisTemplate.opsForList().leftPush("key", "333");
String value = redisTemplate.opsForList().rightPop("key");
System.out.println("value: " + value);
value = redisTemplate.opsForList().rightPop("key");
System.out.println("value: " + value);
value = redisTemplate.opsForList().rightPop("key");
System.out.println("value: " + value);
return "OK";
}
@GetMapping("/testSet")
@ResponseBody
public String testSet() {
redisTemplate.execute((RedisConnection connection) -> {
connection.flushAll();
return null;
});
redisTemplate.opsForSet().add("key", "111", "222", "333");
Set<String> result = redisTemplate.opsForSet().members("key");
System.out.println("result: " + result);
Boolean exists = redisTemplate.opsForSet().isMember("key", "111");
System.out.println("exists: " + exists);
Long count = redisTemplate.opsForSet().size("key");
System.out.println("count: " + count);
redisTemplate.opsForSet().remove("key", "111", "222");
result = redisTemplate.opsForSet().members("key");
System.out.println("result: " + result);
return "OK";
}
@GetMapping("/testHash")
@ResponseBody
public String testHash() {
redisTemplate.execute((RedisConnection connection) -> {
connection.flushAll();
return null;
});
redisTemplate.opsForHash().put("key", "f1", "111");
redisTemplate.opsForHash().put("key", "f2", "222");
redisTemplate.opsForHash().put("key", "f3", "333");
String value = (String) redisTemplate.opsForHash().get("key", "f1");
System.out.println("value: " + value);
Boolean exists = redisTemplate.opsForHash().hasKey("key", "f1");
System.out.println("exists: " + exists);
redisTemplate.opsForHash().delete("key", "f1", "f2");
Long size = redisTemplate.opsForHash().size("key");
System.out.println("size: " + size);
return "OK";
}
@GetMapping("/testZSet")
@ResponseBody
public String testZSet() {
redisTemplate.execute((RedisConnection connection) -> {
connection.flushAll();
return null;
});
redisTemplate.opsForZSet().add("key", "zhangsan", 10);
redisTemplate.opsForZSet().add("key", "lisi", 20);
redisTemplate.opsForZSet().add("key", "wangwu", 30);
Set<String> members = redisTemplate.opsForZSet().range("key", 0, -1);
System.out.println("members: " + members);
Set<ZSetOperations.TypedTuple<String>> membersWithScore = redisTemplate.opsForZSet().rangeWithScores("key", 0, -1);
System.out.println("membersWithScore: " + membersWithScore);
Double score = redisTemplate.opsForZSet().score("key", "zhangsan");
System.out.println("score: " + score);
redisTemplate.opsForZSet().remove("key", "zhangsan");
Long size = redisTemplate.opsForZSet().size("key");
System.out.println("size: " + size);
Long rank = redisTemplate.opsForZSet().rank("key", "lisi");
System.out.println("rank: " + rank);
return "OK";
}
}
ps:redis的简单学习就到这里了,谢谢观看。