易筋SpringBoot 2.1 | 第廿五篇:SpringBoot之Jedis访问Redis

写作时间:2019-09-23
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA

说明

REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

Redis的数据结构,例如以下几种

  1. String: 字符串
  2. Hash: 散列
  3. List: 列表
  4. Set: 集合
  5. Sorted Set: 有序集合

相关资源
Redis 官网:https://redis.io/
Redis 在线测试:http://try.redis.io/

Spring 对 Redis 的支持

  • Spring Data Redis
    • 支持的客户度 Jedis / Lettuce
    • RedisTemplate
    • Redis Repository

Redis 优势

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  2. 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  3. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis 与其他 key - value 缓存产品有以下三个特点:

  1. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  3. Redis支持数据的备份,即master-slave模式的数据备份。

Redis与其他key-value存储有什么不同?

  1. Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

  2. Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Jedis 客户端的简单实用

  • Jedis 不是线程安全的
  • 通过 JedisPool 获得 Jedis 实例
  • 直接使用 Jedis 中的方法

通过 Docker 启动 Redis

官方指引

  • https://hub.docker.com/
    进入镜像中心,搜索redis,第一个就是官方的镜像
  • https://hub.docker.com/_/redis

搜索Redis镜像

% docker search redis
NAME                             DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
redis                            Redis is an open source key-value store that…   7343                [OK]                
bitnami/redis                    Bitnami Redis Docker Image                      127                                     [OK]
sameersbn/redis                                                                  77                                      [OK]
...


获取镜像

  • docker pull redis

查看本地镜像

% docker images redis
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              63130206b0fa        10 days ago         98.2MB

创建启动 Redis

  • docker run -d -p 6379:6379 -v $PWD/data:/data redis

解析:

  • -p 6379:6379 : 将容器的6379端口映射到主机的6379端口

  • -v $PWD/data:/data : 将主机中当前目录下的data挂载到容器的/data

如果已经存在 Redis的镜像,直接启动就好

  • docker start redis

查看Docker中的进程

% docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
a29d10ecd6d5        redis               "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:6379->6379/tcp   elastic_curie

运行Redis客户端,注意要跟Server关联,也即是上面的Container Id

% docker exec -it a29d10ecd6d5 redis-cli

查看Redis 信息

% docker exec -it a29d10ecd6d5 redis-cli
127.0.0.1:6379> info
# Server
redis_version:5.0.5
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:442b43d467cd2b03
redis_mode:standalone
os:Linux 4.9.184-linuxkit x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:8.3.0
process_id:1
run_id:ae99dde4e98d8316ba0fb9ec489a29e1c34a9de6
tcp_port:6379
uptime_in_seconds:163
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8918360
executable:/data/redis-server
config_file:
...

操作hset 命令

127.0.0.1:6379> hset myhash field1 "Hello"
(integer) 1
127.0.0.1:6379> hget myhash field1
"Hello"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "Hello"

1.工程建立

下载已经创建好的Starbucks项目
重命名根文件夹名字的JedisDemo,用Idea打开工程,运行后实际为JPA操作数据。
接下来就改造为Jedis操作Redis数据。

pom.xml增加, Jedis配置


<dependencies>
    <dependency>
       <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
</dependencies>

1.application配置

src > main > resources > application.yml

spring:
  jpa:
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        show_sql: true
        format_sql: true
redis:
  host: localhost
  maxTotal: 5
  maxIdel: 5
  testOnBorrow: true
  

配置Redis的信息

Controller Redis CRUD

zgpeace.spring.starbucks.StarbucksApplication

package zgpeace.spring.starbucks;

import lombok.extern.slf4j.Slf4j;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import zgpeace.spring.starbucks.model.Coffee;
import zgpeace.spring.starbucks.model.CoffeeOrder;
import zgpeace.spring.starbucks.model.OrderState;
import zgpeace.spring.starbucks.repository.CoffeeRepository;
import zgpeace.spring.starbucks.service.CoffeeOrderService;
import zgpeace.spring.starbucks.service.CoffeeService;

import java.util.Map;
import java.util.Optional;

@Slf4j
@EnableTransactionManagement
@EnableJpaRepositories
@SpringBootApplication
public class StarbucksApplication implements ApplicationRunner {
  @Autowired
  private CoffeeService coffeeService;
  @Autowired
  private JedisPool jedisPool;
  @Autowired
  private JedisPoolConfig jedisPoolConfig;

  @Bean
  @ConfigurationProperties("redis")
  public JedisPoolConfig jedisPoolConfig() {
    return new JedisPoolConfig();
  }

  @Bean(destroyMethod = "close")
  public JedisPool jedisPool(@Value("localhost") String host) {
    return new JedisPool(jedisPoolConfig(), host);
  }

  @Override
  public void run(ApplicationArguments args) throws Exception {
    log.info(jedisPoolConfig.toString());

    try (Jedis jedis = jedisPool.getResource()) {
      coffeeService.findAllCoffee().forEach(c -> {
        jedis.hset("starbucks-menu",
            c.getName(),
            Long.toString(c.getPrice().getAmountMinorLong()));
      });

      Map<String, String> menu = jedis.hgetAll("starbucks-menu");
      log.info("Menu: {}", menu);

      String price = jedis.hget("starbucks-menu", "espresso");
      log.info("espresso - {}",
          Money.ofMinor(CurrencyUnit.of("CNY"), Long.parseLong(price)));

    }
  }

  public static void main(String[] args) {
    SpringApplication.run(StarbucksApplication.class, args);
  }

}

运行数据入库和查询日志如下:

JedisPoolConfig [lifo=true, fairness=false, maxWaitMillis=-1, minEvictableIdleTimeMillis=60000, softMinEvictableIdleTimeMillis=-1, 
numTestsPerEvictionRun=-1, evictionPolicyClassName=org.apache.commons.pool2.impl.DefaultEvictionPolicy, testOnCreate=false, 
testOnBorrow=true, testOnReturn=false, testWhileIdle=true, timeBetweenEvictionRunsMillis=30000, 
blockWhenExhausted=true, jmxEnabled=true, jmxNamePrefix=pool, jmxNameBase=null, maxTotal=5, maxIdle=5, minIdle=0]

Menu: {mocha=3000, espresso=2000, capuccino=2500, latte=2500, macchiato=3000}

espresso - CNY 20.00

注释: 程序运行必要条件,必须启动Docker > 加载Redis镜像到容器(docker start redis)。

  1. 配置Redis信息起效:maxTotal=5, maxIdle=5, testOnBorrow=true
  2. 把coffee的价格都放到hset里面,Menu: {mocha=3000, espresso=2000, capuccino=2500, latte=2500, macchiato=3000}
  3. 读取espresso - CNY 20.00

总结

恭喜你,学会了Redis操作数据。
代码下载:

https://github.com/zgpeace/Spring-Boot2.1/tree/master/Nosql/JedisDemo

参考

https://redis.io
http://try.redis.io/
https://hub.docker.com/_/redis
https://www.runoob.com/redis/redis-tutorial.html
https://www.runoob.com/docker/docker-install-redis.html

https://github.com/zgpeace/Spring-Boot2.1/tree/master/db/DemoDBStarbucks

https://github.com/geektime-geekbang/geektime-spring-family/tree/master/Chapter%204/jedis-demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值