Redis 在 Spring Boot 2.x 中相比 1.5.x 版本,有一些改变。redis 默认链接池,1.5.x 使用了 jedis,而2.x 使用了 lettuce

Redis 接入 Spring Boot 缓存,使用的注解跟 Ehcache 接入缓存的注解是一样的,Spring Boot 缓存应用 Ehcache 入门教程

安装 Redis 请参见 如何在 Mac 下安装 Redis 和 如何在 Window 下安装 Redis

本文仅仅适用

  • spring boot 2.x
  • redis
  • jdk 1.8+

本项目源码下载

0 注意

本章代码与 Spring Boot 缓存应用 Ehcache 入门教程 基本是相同的,不同的是 Ehcache 换成了 Redis。有几点需要注意

  • 本示例代码是基于 Spring Boot 2.1.6,Redis for Spring Boot 2.x 的配置与 Spring Boot 1.5.x 配置有细微的差别,主要是 Redis 默认连接池区别。
  • 实体类 UserDO 必须要求支持序列化,继承与 implements Serializable
  • Redis 没有进行 xml 配置文件配置,使用了 @Configuration 进行配置

1 新建 Spring Boot Maven 示例工程项目

注意:是用来 IDEA 开发工具

  1. File > New > Project,如下图选择 Spring Initializr 然后点击 【Next】下一步
  2. 填写 GroupId(包名)、Artifact(项目名) 即可。点击 下一步

    groupId=com.fishpro

    artifactId=redis
  3. 选择依赖 Spring Web Starter 前面打钩。
  4. 项目名设置为 spring-boot-study-redis.

2 引入依赖 Pom

  • fastjson
  • redis
 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

3 Redis 使用注解实现缓存

使用注解方式,不需要做配置也可以运行示例,我们这里不用编写配置文件,只要在启动类上加上 @EnableCaching 注解就可以使用

3.1 示例代码

整个业务代码包括了

模拟一个增删改查来设置缓存示例,包括了

  • UserService 用户服务类
  • UserServiceImpl 用户服务实现类
  • UserController 用户控制层类使用了 RestController

UserService 用户接口(路径 src/main/java/com/fishpro/redis/service/UserService.java)

public interface UserService {

    List<UserDO> list();
UserDO get(Integer id);
UserDO save(UserDO user);
UserDO update(UserDO user);
void delete(Integer id); }

UserServiceImpl(路径 src/main/java/com/fishpro/redis/service/impl/UserServiceImpl.java)

// fpcache 对应 ehcache.xml 中的 fpcache 节点
@CacheConfig(cacheNames = {"fpcache"})
@Service
public class UserServiceImpl implements UserService {
@Override
@Cacheable("fpcache")
public List<UserDO> list() {
List<UserDO> list=new ArrayList<>();
list.add( new UserDO(1,"fishpro","123456",1));
list.add( new UserDO(2,"fishpro2","123456",1));
list.add( new UserDO(3,"fishpro3","123456",1));
System.out.println("获取用户列表使用 @Cacheable 注意执行第二次的时候不会有本语句输出了,部分删除掉缓存");
return list;
} @Override
@Cacheable(value = "fpcache",key = "#id")
public UserDO get(Integer id) {
System.out.println("获取单个用户 get user by"+id);
return new UserDO(1,"fishpro","123456",1); } @Override
@CachePut(value = "fpcache",key = "#user.id")
public UserDO save(UserDO user) {
System.out.println("保存用户使用 @CachePut 每次都会执行语句并缓存 save user by "+user.getUserName());
return user; } @Override
@CachePut(value = "fpcache",key = "#user.id")
public UserDO update(UserDO user) {
System.out.println("更新用户使用 @CachePut 每次都会执行语句并缓存 update user by "+user.getUserName());
return user; } @Override
@CacheEvict(allEntries = true)
public void delete(Integer id) {
System.out.println("删除用户根据用户ID,如果 allEntries = true 则不论 key 是啥都全部删除缓存"+id);
}
}

UserController(路径 src/main/java/com/fishpro/redis/controller/UserController.java)


@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/test")
public String testCache(){
System.out.println("============以下第一次调用 ================");
userService.list();
userService.get(1);
userService.save(new UserDO(1,"fishpro","123456",1));
userService.update(new UserDO(1,"fishpro","123456434",1)); System.out.println("============以下第二次调用 观察 list 和 get 方法 ================"); userService.list();
userService.get(1);
userService.save(new UserDO(1,"fishpro","123456",1));
userService.update(new UserDO(1,"fishpro","123456434",1)); System.out.println("============以下第三次调用 先删除 观察 list 和 get 方法 ================");
userService.delete(1);
userService.list();
userService.get(1);
userService.save(new UserDO(1,"fishpro","123456",1));
userService.update(new UserDO(1,"fishpro","123456434",1));
return "";
}
}

3.2 运行

右键 RedisApplication 选择 Run RedisApplication 在浏览器中输入 http://localhost:8080/test

4 Redis 使用 RedisTemplate 方式实现

与使用注解方式不同,注解方式可以零配置,只需引入依赖并在启动类上加上 @EnableCaching 注解就可以使用;而使用 RedisTemplate 方式麻烦些,需要做一些配置

本示例中设置 redis 为 StringRedisSerializer

4.1 配置

#2.x版本中由于引入了不同客户端,需要指定配置哪种连接池
#jedis客户端
spring:
cache:
type: redis
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0

然后写个 RedisConfig.java 配置类,本示例中设置 redis 为 StringRedisSerializer

@Configuration
public class RedisConfig extends CachingConfigurerSupport { @Bean
public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object,Object> template = new RedisTemplate<>();
//设置连接池
template.setConnectionFactory(redisConnectionFactory);
StringRedisSerializer stringRedisSerializer=new StringRedisSerializer(); template.setValueSerializer(serializer);
//hash value的序列化问题
template.setHashValueSerializer(serializer);
//key 的序列化
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer()); return template;
} @Bean
public CacheManager cacheManager(RedisConnectionFactory factory){ // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置
config = config.entryTtl(Duration.ofMinutes(1))
.disableCachingNullValues(); // 不缓存空值 // 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("my-redis-cache1");
cacheNames.add("my-redis-cache2"); // 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("my-redis-cache1", config);
configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); // 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
}

4.3 Redis 数据结构简介

Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

结构 结构存储的值范围
String 可以是字符串、整数或者浮点数
List 一个链表,链表上的每个节点都包含了一个字符串
Set 包含字符串的无序收集器(unorderedcollection),并且被包含的每个字符串都是独一无二的、各不相同
Hash 包含键值对的无序散列表
Zset 字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定

4.4 StringRedisTemplate 与 RedisTemplate

StringRedisTemplate 与 RedisTemplate 区别

  • StringRedisTemplate 继承 RedisTemplate
  • RedisTemplate 是一个泛型类,而 StringRedisTemplate 不是
  • StringRedisTemplate 只能对 key=String,value=String 的键值操作。
  • 他们各自序列化的方式不同,但是都会得到一个字节数组。StringRedisTemplate 使用的是 StringRedisSerializer 类;RedisTemplate 使用的是 JdkSerializationRedisSerializer 类。反序列化,则是一个得到 String,一个得到 Object
  • 两者的数据是不共通的,StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate中 的数据。

4.5 代码实例

RedisController(路径 src/main/java/com/fishpro/redis/controller/RedisController(路径.java)

package com.fishpro.redis.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import java.util.*;
import java.util.function.Consumer; @RestController
public class RedisController { @Autowired
RedisTemplate redisTemplate; @Autowired
StringRedisTemplate stringRedisTemplate; public static final String CACHE_PREFIX = "FP:"; @RequestMapping("/redis")
public String testRedis(){ System.out.println("字符串和散列Value和Hash-------------------------------------------------------");
//set字符串
redisTemplate.opsForValue().set("string_key", "string value");
System.out.println("-------------set字符串-------------------: " + redisTemplate.opsForValue().get("string_key")); //注意这里使用了JDK的序列化器,所以redis保存时不是整数,不能运算
redisTemplate.opsForValue().set("int_key", "1");
System.out.println("-------------set int_key-------------------: " + redisTemplate.opsForValue().get("int_key")); stringRedisTemplate.opsForValue().set("int", "1");
System.out.println("-------------stringRedisTemplate set int-------------------: " + redisTemplate.opsForValue().get("int")); //使用运算
stringRedisTemplate.opsForValue().increment("int", 1);
System.out.println("-------------使用运算+1-------------------: " + redisTemplate.opsForValue().get("int")); //定义一个hashmap散列
Map<String, String> hash = new HashMap<String, String>();
hash.put("field1", "value1");
hash.put("field2", "value2");
//存入一个散列数据类型
stringRedisTemplate.opsForHash().putAll("hash", hash);
System.out.println("-------------存入一个散列数据类型-------------------: ");
System.out.println("-------------map 遍历-------------------: ");
redisTemplate.opsForHash().entries("hash").forEach((k, v) -> {
System.out.println(k + ": " + v);
});
System.out.println("-------------map->set 遍历-------------------: ");
redisTemplate.opsForHash().keys("hash").forEach(key -> {
System.out.println(key + ": " + redisTemplate.opsForHash().get("hash", key));
});
//新增一个字段
stringRedisTemplate.opsForHash().put("hash", "field3", "value3");
System.out.println("-------------新增一个字段 field3-------------------: ");
redisTemplate.opsForHash().entries("hash").forEach((k, v) -> {
System.out.println(k + ": " + v);
});
//绑定散列操作的key,这样可以连续对同一个散列数据进行操作
BoundHashOperations hashOps = stringRedisTemplate.boundHashOps("hash");
//删除两个字段
hashOps.delete("field1", "field2");
System.out.println("-------------删除两个字段 field1 field2-------------------: ");
hashOps.entries().forEach((k, v) -> {
System.out.println(k + ": " + v);
});
//新增一个字段
hashOps.put("field5", "value5");
System.out.println("-------------新增一个字段 field5-------------------: ");
hashOps.entries().forEach((k, v) -> {
System.out.println(k + ": " + v);
}); System.out.println("列表(链表)List-------------------------------------------------------");
//list 链表
//插入两个链表,注意它们在链表中的顺序
//链表从左到右的顺序为v10,v8,v6,v4,v2
stringRedisTemplate.opsForList().leftPushAll("list1", "v2", "v4", "v6", "v8", "v10");
System.out.println("----------链表从左到右的顺序为v10,v8,v6,v4,v2----------------:");
stringRedisTemplate.opsForList().range("list1", 0, stringRedisTemplate.opsForList().size("list1") - 1).forEach(s -> System.out.println(s)); //从左到右顺序为v1,v2,v3,v4,v5,v6
stringRedisTemplate.opsForList().rightPushAll("list2", "v1", "v2", "v3", "v4", "v5", "v6");
System.out.println("----------从左到右顺序为v1,v2,v3,v4,v5,v6----------------:");
stringRedisTemplate.opsForList().range("list2", 0, stringRedisTemplate.opsForList().size("list2") - 1).forEach(s -> System.out.println(s));
// 绑定list2链表操作
BoundListOperations listOps = stringRedisTemplate.boundListOps("list2");
//从右边弹出一个成员
String result1 = (String)listOps.rightPop();
System.out.println("----------从右边弹出一个成员----------------: " + result1);
listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
//获取定位元素,redis从0开始运算
String result2 = (String)listOps.index(1);
System.out.println("----------获取定位元素,redis从0开始运算----------------: " + result2);
listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
//从左边插入链表
listOps.leftPush("v0");
System.out.println("----------从左边插入链表----------------: " + "v0");
listOps.range(0, listOps.size() - 1).forEach(s -> System.out.println(s));
//链表长度
Long size = listOps.size();
//求链表下标区间成员,整个链表下标范围为0到size-1,这里不取最后一个元素
List elements = listOps.range(0, size - 2);
System.out.println("----------求链表下标区间成员0->size-2 ----------------: " + "v0");
elements.forEach(s -> System.out.println(s)); System.out.println("集合Set示例-------------------------------------------------------");
//set
//请注意,这里v1重复两次,因为集合不允许重复,所以只是插入5个成员到集合中
stringRedisTemplate.opsForSet().add("set1", "v1", "v1", "v2", "v3", "v4", "v5");
stringRedisTemplate.opsForSet().add("set2", "v2", "v4", "v6", "v8");
//绑定set1集合操作
BoundSetOperations setOps = stringRedisTemplate.boundSetOps("set1");
//增加两个元素
setOps.add("v6", "v7");
//删除两个元素
setOps.remove("v1", "v7");
//返回所有元素
Set set1 = setOps.members();
// 成员数
size = setOps.size();
//求交集
Set inner = setOps.intersect("set2");
//求交集并且用新集合inter保存
setOps.intersectAndStore("set2", "inner");
//求差集
Set diff = setOps.diff("set2");
//求差集,并且用新集合diff保存
setOps.diffAndStore("set2", "diff");
//求并集
Set union = setOps.union("set2");
//求并集并且用新集合union保存
setOps.unionAndStore("set2", "union"); //ZSET
Set<ZSetOperations.TypedTuple<String>> typedTupleSet = new HashSet<>();
for (int i = 1; i <= 9; i++) {
//分数
double score = i * 0.1;
//创建一个TypedTuple对象,存入值和分数
ZSetOperations.TypedTuple<String> typedTuple = new DefaultTypedTuple<String>("value" + i, score);
typedTupleSet.add(typedTuple);
}
//往有序集合插入元素
stringRedisTemplate.opsForZSet().add("zset1", typedTupleSet);
//绑定zset1有序集合操作
BoundZSetOperations zsetOps = stringRedisTemplate.boundZSetOps("zset1");
System.out.println("------------init----------------");
zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() { @Override
public void accept(Object t) {
ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
System.out.println(s.getValue() + " : " + s.getScore());
} });
//增加一个元素
zsetOps.add("value10", 0.26);
System.out.println("------------增加一个元素 value10----------------");
zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() { @Override
public void accept(Object t) {
ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
System.out.println(s.getValue() + " : " + s.getScore());
} });
// 获得range 1---6
Set<String> setRange = zsetOps.range(1, 6);
System.out.println("------------获得range 1---6---------------");
Iterator itor = setRange.iterator();
if (itor.hasNext()) {
String s = (String)itor.next();
System.out.println(s);
}
//按分数排序获得有序集合
Set<String> setScore = zsetOps.rangeByScore(0.2, 0.6);
System.out.println("------------按分数排序获得有序集合 (0.2, 0.6)---------------");
Iterator itor2 = setScore.iterator();
if (itor.hasNext()) {
String s = (String)itor.next();
System.out.println(s);
}
//自定义范围
RedisZSetCommands.Range range = new RedisZSetCommands.Range();
range.gt("value3");//大于value3
// range.gte("value3");//大于等于value3
// range.lt("value8");//小于value8
range.lte("value8");//小于等于value8
//按值排序,请注意这个排序是按字符串排序
Set<String> setLex = zsetOps.rangeByLex(range);
System.out.println("------------自定义范围 (value3, value8)---------------");
Iterator itor3 = setLex.iterator();
if (itor.hasNext()) {
String s = (String)itor.next();
System.out.println(s);
} //删除元素
zsetOps.remove("value9", "value2");
System.out.println("------------删除元素 value9, value2---------------");
zsetOps.rangeWithScores(0, zsetOps.size() - 1).forEach(new Consumer() { @Override
public void accept(Object t) {
ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
System.out.println(s.getValue() + " : " + s.getScore());
} }); //求分数
Double score = zsetOps.score("value8");
System.out.println("-----------求分数 value8---------------:" + score);
//在下标区间下,按分数排序,同时返回value和score
Set<ZSetOperations.TypedTuple<String>> rangeSet = zsetOps.rangeWithScores(1, 6);
System.out.println("-----------在下标区间下,按分数排序 (1, 6)---------------");
rangeSet.forEach(new Consumer() { @Override
public void accept(Object t) {
ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
System.out.println(s.getValue() + " : " + s.getScore());
} });
//在分数区间下,按分数排序,同时返回value和score
Set<ZSetOperations.TypedTuple<String>> scoreSet = zsetOps.rangeByScoreWithScores(0.1, 0.6);
System.out.println("-----------在分数区间下,按分数排序 (0.1, 0.6)---------------");
scoreSet.forEach(new Consumer() { @Override
public void accept(Object t) {
ZSetOperations.TypedTuple<String> s = (ZSetOperations.TypedTuple)t;
System.out.println(s.getValue() + " : " + s.getScore());
} });
//按从大到小排序
Set<String> reverseSet = zsetOps.reverseRange(0, zsetOps.size() - 1);
System.out.println("-----------按从大到小排序---------------");
reverseSet.forEach(s -> System.out.println(s)); System.out.println("redis开启事务--------------------------");
redisTemplate.opsForValue().set("key1", "value1");
List list = (List)redisTemplate.execute((RedisOperations operations) -> {
//设置要监控的Key
operations.watch("key1");
//开启事务。在exec命令执行前,全部都只是进入队列
operations.multi();
operations.opsForValue().set("key2", "value2");
//获取值为null,因为redis只是把命令放入队列
Object value2 = operations.opsForValue().get("key2");
System.out.println("命令在队列中,所以key2为null【" + value2 + "】");
operations.opsForValue().set("key3", "value3");
System.out.println("命令在队列中,所以key3为null【" + value2 + "】");
//执行exec命令,将先判断key1是否在监控后被修改过,如果是则不执行事务,否则就执行事务
return operations.exec();
}); System.out.println("redis流水线--------------------------");
Long start = System.currentTimeMillis();
List list = redisTemplate.executePipelined((RedisOperations operations) -> {
for (int i = 1; i <= 100000; i++) {
operations.opsForValue().set("pipeline_" + i, "value" + i);
String value = (String)operations.opsForValue().get("pipeline_" + i);
if (i == 100000) {
System.out.println("命令在队列中,所以值为null【" + value + "】");
}
}
return null;
});
Long end = System.currentTimeMillis();
System.out.println("耗时: " + (end - start) + "毫秒"); return "";
}
}

4.6 运行示例

右键 RedisApplication 选择 Run RedisApplication 在浏览器中输入 http://localhost:8080/redis

本项目源码下载


参考

https://www.cnblogs.com/maria-ld/p/10010219.html

https://blog.csdn.net/Sadlay/article/details/83821629

Spring Boot 2.x 缓存应用 Redis注解与非注解方式入门教程的更多相关文章

  1. Spring Boot移除内嵌Tomcat,使用非web方式启动

    前言:当我们使用Spring Boot编写了一个批处理应用程序,该程序只是用于后台跑批数据,此时不需要内嵌的tomcat,简化启动方式使用非web方式启动项目,步骤如下: 1.在pom.xml文件中去 ...

  2. Spring Boot中的缓存支持(一)注解配置与EhCache使用

    Spring Boot中的缓存支持(一)注解配置与EhCache使用 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决 ...

  3. Spring Boot 自带缓存及结合 Redis 使用

    本文测试环境: Spring Boot 2.1.4.RELEASE + Redis 5.0.4 + CentOS 7 自带缓存 如果没有使用缓存中间件,Spring Boot 会使用默认的缓存,我们只 ...

  4. Spring Boot中使用缓存

    Spring Boot中使用缓存 随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一. 原始的使 ...

  5. spring(三、spring中的eheche缓存、redis使用)

    spring(三.spring中的eheche缓存.redis使用) 本文主要介绍为什么要构建ehcache+redis两级缓存?以及在实战中如何实现?思考如何配置缓存策略更合适?这样的方案可能遗留什 ...

  6. 阿里P7级教你如何在Spring Boot应用程序中使用Redis

    在Spring Boot应用程序中使用Redis缓存的步骤: 1.要获得Redis连接,我们可以使用Lettuce或Jedis客户端库,Spring Boot 2.0启动程序spring-boot-s ...

  7. Spring Boot 集成 Ehcache 缓存,三步搞定!

    作者:谭朝红 www.ramostear.com/articles/spring_boot_ehcache.html 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序 ...

  8. 基于Spring Cache实现二级缓存(Caffeine+Redis)

    一.聊聊什么是硬编码使用缓存? 在学习Spring Cache之前,笔者经常会硬编码的方式使用缓存. 我们来举个实际中的例子,为了提升用户信息的查询效率,我们对用户信息使用了缓存,示例代码如下: @A ...

  9. spring boot guava cache 缓存学习

    http://blog.csdn.net/hy245120020/article/details/78065676 ****************************************** ...

随机推荐

  1. mysql忘记密码,更改密码

    对MySQL有研究的读者,可能会发现MySQL更新很快,在安装方式上,MySQL提供了两种经典安装方式:解压式和一键式,虽然是两种安装方式,但我更提倡选择解压式安装,不仅快,还干净.在操作系统上,My ...

  2. JarvisOJ - Writeup(5.31更新)

    此篇用来记录我在jarivsOJ上的一些题解,只给解题思路,不放flag Misc 0x01 You Need Python(300) 题目有两个文件,一个py文件,另一个是经过编码的key 文件ke ...

  3. xv6 trapframe定义的位置

    在x86.h的最下面,真是把我找吐了,MD

  4. Docker 基本命令和使用

    Docker 基本命令 systemctl start docker : 启动 Docker systemctl stop docker : 停止 Docker systemctl restart d ...

  5. 08day 操作命令以及目录结构

    yum /var/log目录(日志文件)两个重要目录:message--记录系统或服务程序运行状态信息 secure--记录用户登录信息 tail -f 查看日志方法    head 查问文件头部

  6. NUMPY的学习之路(2)——索引,合并,分割,赋值

    一.索引 1.1numpy数组的转置 A=np.arange(3,15).reshape(3,4) print(A) print(A[2][0]) print(A[2,1]) print(A[2,:] ...

  7. HBO《硅谷》中的二进制码

    先反思一下……这两天感觉除了coding,没有很好地去学习专业课.心神不定 于是,就想看下硅谷,来提升一下自己的coding执行力…… 然后,我就在看剧的时候,看到了这么一张图:‘ 然后嘛…… 我就想 ...

  8. PHP通过thrift2访问HBASE

    前一段时间需要在网页上显示HBASE查询的结果,考虑用PHP来实现,在网上搜了一下,普遍都是用thrift作为接口来实现的.​ 参考博文:​ http://www.cnblogs.com/scotom ...

  9. Kali国内源更新sources.list

    Kali国内源更新sources.list   更新源,个人推荐中科大leafpad /etc/apt/sources.list   #中科大   deb http://mirrors.ustc.ed ...

  10. pysftp-tools

    import pysftp import paramiko import os import unittest import json import warnings warnings.filterw ...