数据类型

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:

  • 字符串 —— string

  • 哈希 —— hash

    适合存储对象。

  • 列表 —— list

    按照插入顺序排序,可以有重复元素。可以用来做任务队列。

  • 集合 —— set

    无序集合,没有重复元素(后插入的元素会覆盖已有的相同元素)。

  • 有序集合 —— sorted set

    有序集合(使用分值进行排序),没有重复元素。


常用命令

Redis命令符不区分大小写,但是key是区分大小写的。 更多命令请参考Redis中文网

字符串操作命令

SET key value
  • 设置指定key的值。
  • key相同的情况下,后设的值会覆盖前面的值。
GET key
  • 获取指key的值。
SETEX key seconds value
  • 设置指定key的值,并将key的过期时间设为seconds秒。
SETNX key value
  • 只有在key不存在时设置key的值。

  • 如:

    > SETNX key1 value1
    1
    > SETNX key1 value2
    0
    > GET key1
    value1
    

哈希操作命令

Redis hash 是一个string类型的fieldvalue的映射表,hash特别适合用于存储对象。

HSET key field value
  • 将哈希表key种的字段field的值设为value。
HGET key field
  • 获取存储在哈希表中指定字段的值。
HDEL key field
  • 删除存储在哈希表中的指定字段。
HKEYS key
  • 获取哈希表中所有字段。
HVALS key
  • 获取哈希表中所有值。
HGETALL key
  • 获取在哈希表中指定key的所有字段和值。

列表操作命令

LPUSH key value1 [value2 ...]
  • 将一个或多个值插入到列表头部。
LRANGE key start stop
  • 获取列表指定范围内的元素(startstop,索引从0开始)。
RPOP key
  • 移除并获取列表最后一个元素。
LLEN key
  • 获取列表长度。
BRPOP key1 [key2 ...] timeout
  • 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时(timeout秒)或(在指定的key中)发现可弹出元素为止。

集合操作命令

Redis set是string类型的无序集合,集合成员是唯一的。

SADD key member1 [member2 ...]
  • 向集合添加一个或多个成员。
SMEMBERS key
  • 返回集合中的所有成员。
SCARD key
  • 获取集合的成员数。
SINTER key1 [key2 ...]
  • 返回给定所有集合的交集。
SUNION key1 [key2 ...]
  • 返回所有给定集合的并集。
SDIFF key1 [key2 ...]
  • 返回给定所有集合的差集(左差集,即key1集合中在其他集合没有的元素集合)。
SREM key member1 [member2 ...]
  • 移除集合中一个或多个成员。

有序集合操作命令

Redis sorted set 是string类型元素的集合,且不允许重复的成员。每个元素都会关联一个double类型的分数(score)。Redis通过分数来为集合中的成员进行从小到大排序,有序集合的成员是唯一的,但分数却可以重复。

ZADD key score1 member1 [score2 member2 ...]
  • 向有序集合添加一个或多个成员,或者更新已存在成员的分数。
ZRANGE key start stop [WITHSCOES]
  • 通过索引区间返回有序集合中指定区间内的成员。使用WITHSCOES可以返回成员的分数。
ZINCRBY key increment member
  • 有序集合中对指定成员的分数加上增量increment
ZREM key member [member ...]
  • 移除有序集合中的一个或多个成员。

通用命令

KEYS pattren
  • 查找所有符合给定模式(pattern)的key。
EXISTS key
  • 检查给定key是否存在。
TYPE key
  • 返回key所存储的值的类型。
TTL key
  • 返回给定key的剩余生存时间(TTL,time to live),以秒为单位。
DEL key1 [key2 ...]
  • 该命令用于在key存在时删除key。

  • 如:

    > TTL key
    -1
    

    返回-1表示永久存活。

切换数据库

Redis 默认是在0号数据库中执行操作。如果想要切换数据库,可以使用:

SELECT number

如:

127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]>

Redis 默认提供了16个数据库。

要修改该配置可以在redis.conf中修改databases的数量。

databash 16

Spring Data Redis

依赖

Spring Data Redis的依赖坐标为:

<!-- Spring Date Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <!-- version在spring-boot-starter-parent中定义 -->
</dependency>

配置

application.yml

spring:
  application:
    name: springdataredis-demo
  # Redis相关配置
  data:
    redis:
      host: localhost
      port: 6379
      password: 123456
      database: 0       # 操作0号数据库
      jedis:
        # Redis连接池配置
        pool:
          max-active: 8 # 最大连接数
          max-wait: 1ms # 连接池最大阻塞等待时间
          max-idle: 4   # 连接池中的最大空闲连接
          min-idle: 0   # 连接池中的最小空闲连接

配置类(修改默认序列化器,防止因序列化在Redis上产生乱码,但并不妨碍读值。因为读取时会自动反序列化):

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {

        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

        // 默认的Key序列化器为:JdkSerializationRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        redisTemplate.setConnectionFactory(connectionFactory);

        return redisTemplate;
    }

}

测试

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringDataRedisTest {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 操作字符串类型数据
     */
    @Test
    public void testString() {
        // 获得String类型数据操作对象
        ValueOperations valueOperations = redisTemplate.opsForValue();

        valueOperations.set("city", "guangzhou");

        String city = (String) valueOperations.get("city");
        System.out.println(city);

        // 设置超时
        valueOperations.set("key1", "value1", 10L, TimeUnit.SECONDS);

        // 不存在才设置
        Boolean setIfAbsent1 = valueOperations.setIfAbsent("city", "foshang");
        System.out.println(Boolean.TRUE.equals(setIfAbsent1) ? "city设置成功" : "city已存在");
        Boolean setIfAbsent2 = valueOperations.setIfAbsent("city_name", "foshang",
                                                   10L, TimeUnit.SECONDS);
        Object cityName = valueOperations.get("city_name");
        System.out.println(setIfAbsent2 ? "city_name设置成功:" + cityName
                                        : "city_name已存在");
    }

    /**
     * 操作哈希类型数据
     */
    @Test
    public void testHash() {
        HashOperations hashOperations = redisTemplate.opsForHash();

        String id = "002";
        // 存值
        hashOperations.put(id, "name", "xiaoming");
        hashOperations.put(id, "age", "20");
        hashOperations.put(id, "address", "guangzhou");

        // 取值
        String name = (String) hashOperations.get(id, "name");
        String age = (String) hashOperations.get(id, "age");
        String address = (String) hashOperations.get(id, "address");
        System.out.println("name:" + name + ",age:" + age + ",address:" + address);

        // 获取hash结构中的所有字段
        Set keys = hashOperations.keys(id);
        for (Object key : keys) {
            System.out.println(key);
        }

        // 删除
        //hashOperations.delete(keys, "address", "age");

        // 获得hash结构中的所有值
        List<String> values = hashOperations.values(id);
        for (String value : values) {
            System.out.println(value);
        }
    }

    /**
     * 操作列表类型数据
     */
    @Test
    public void testList() {
        ListOperations listOperations = redisTemplate.opsForList();

        String key = "mylist";
        // 存储
        listOperations.leftPush(key, "a");
        listOperations.leftPushAll(key, "b", "c", "d");

        // 取值
        System.out.printf("入队:");
        List<String> myList = listOperations.range(key, 0, -1);
        for (String s : myList) {
            System.out.printf(s + " ");
        }
        System.out.println();

        // 获得列表长度 llen
        int size = listOperations.size(key).intValue();
        System.out.printf("出队:");
        for (int i = 0; i < size; i++) {
            // 出队列
            String element = (String) listOperations.rightPop(key);
            System.out.printf(element + " ");
        }
        System.out.println();
    }

    /**
     * 操作集合类型数据
     */
    @Test
    public void testSet() {
        SetOperations setOperations = redisTemplate.opsForSet();

        String key = "myset";
        // 存值
        setOperations.add(key, "a", "b", "c", "d", "a");

        // 取值
        Set<String> myset = setOperations.members(key);
        for (String s : myset) {
            System.out.printf(s + " ");
        }
        System.out.println();

        // 删除成员
        setOperations.remove(key, "a", "b");

        // 取值
        myset = setOperations.members(key);
        for (String s : myset) {
            System.out.printf(s + " ");
        }
        System.out.println();
    }

    /**
     * 操作有序集合类型数据
     */
    @Test
    public void testZset() {
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();

        String key = "myZset";
        // 存储
        zSetOperations.add(key, "a", 10.);
        zSetOperations.add(key, "b", 11.);
        zSetOperations.add(key, "c", 12.);
        zSetOperations.add(key, "d", 13.);
        zSetOperations.add(key, "a", 14.);

        // 取值
        Set<String> range = zSetOperations.range(key, 0, -1);
        for (String s : range) {
            System.out.printf(s + " ");
        }
        System.out.println();

        // 修改分数
        zSetOperations.incrementScore(key, "b", 20.);

        // 删除成员
        zSetOperations.remove(key, "a", "c");

        // 取值
        range = zSetOperations.range(key, 0, -1);
        for (String s : range) {
            System.out.printf(s + " ");
        }
        System.out.println();
    }

    /**
     * 通用操作
     */
    @Test
    public void testCommon() {
        // 获取Redis中所有key
        Set<String> keys = redisTemplate.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }

        // 判断m某个key是否存在
        Boolean hasKey = redisTemplate.hasKey("linner");
        System.out.println(hasKey ? "linner存在" : "linner不存在");

        // 删除指定key
        redisTemplate.delete("myZset");

        // 获取指定key对应的value的数据类型
        DataType dataType = redisTemplate.type("myset");
        System.out.println(dataType.name());
    }
}