自学内容网 自学内容网

Redis 数据结结构(一)—字符串、哈希表、列表

Redis(版本7.0)的数据结构主要包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)、超日志(HyperLogLog)、位图(Bitmap)、地理坐标(Geo)、流(Stream)。

1 字符串 String

键和值既可以是文字也可以是二进制数据。

赋值与读取

单个:GET、SET、GETSET(获取旧值并用新值替换)

批量操作:MGET、MSET、MSTNX

字符串

字符串的字节长度:STRLEN

获取字符串指定索引范围上的内容:GETRANGE

对字符串的指定索引范围进行设置:SETRANGE

追加新内容到值的末尾:APPEND

数值运算

整数运算(不可用于浮点数运算):INCRBY、INCR、DECRBY、DECR

浮点数(可用于整数运算):INCRBYFLOAT

表 字符串数据结构相关命令

NX (Non-Existing):字段不存在则赋值,否则不操作。

XX(Existing):字段存在则赋值,否则不操作。

图 字符串的索引

1.1 示例

限速器:为了保障系统的安全性和性能,并保证系统的重要资源不会滥用。系统的会对用户的行为做些限制: 例如,在一定时间内,用户只能对某个资源访问5次,否则只能再等待下个时间段来访问。

public class SPeedLimiter {

    private final static Jedis jedis = RedisPool.getRedis();
    private final static String SPEED_LIMIT_KEY = "speed_limit_str::%s";

    public static void execute(String ip) {
        Long count = jedis.incr(String.format(SPEED_LIMIT_KEY, ip));
        if (count > 5) {
            System.out.println("操作满5次,请稍后再操作");
            return;
        }
        System.out.println("操作成功:" + ip);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 6; i++) {
            execute("127.0.0.1");
        }
    }
}

2 散列(哈希表)Hash

Redis的散列表是一种存储键值对的数据结构。类似于Java的HashMap。但是其键和值只能是字符串(或字节)类型,不能嵌套。

赋值与读取

单个:HSET(也可以批量设置)、HSETNX、HGET

批量操作:HMSET、HMGET

数值运算

HINCRBY、HINCRBYFLOAT

散列

字段相关:HSTRLEN(字段值字节长度)、HEXISTS(检查字段是否存在)、HDEL(删除字段)

散列相关:HLEN(字段数量)、HKEYS(获取所有字段)、HVALS(获取所有值)、HGETALL(所有字段和值)

表 散列数据结构相关命令

2.1 与字符串结构对比

字符串

字符串键命令提供的操作比散列键更为丰富;

键过期功能针对的是整个键,用户无法为散列中不同字段设置不同的过期时间。

散列

只需在数据库里创建一个键,就可以把任意多的字段和值聚合在一起;

可以有效地组织起相关的多项数据,让程序产生给更容易操作的数,使得针对数据的批量操作变得更方便。

表 散列与字符串数据结构对比

2.2 示例

短网址生成:遇到很长的网址时,我们会将其转换为相应的短网址,用这个短网址访问的内容和原网址是一样的。

原理:将需要转换的网址与数据库的id相关联,然后把这个id值转换为特定的字符串。这样就使用“ 服务 + /特定字符串”的形式进行访问时,后端根据这个字符串查找原网址,然后跳转至原网址。

public class ShortURLGenerator {

    private final static String SHORT_URL_ID_COUNTER_KEY = "short_url_id_counter";
    private final static String SHORT_URL_HASH_KEY = "short_url_hash";
    private final static String START_URL = "http://localhost:8080/";

    private final static Jedis jedis = RedisPool.getRedis();

    public static String generateShortUrl(String targetUrl) {
        Long id = jedis.incr(SHORT_URL_ID_COUNTER_KEY);
        jedis.hset(SHORT_URL_HASH_KEY,id.toString(),targetUrl);
        return START_URL + id;
    }

    public static String resolutionUrl(String url) {
        if (url == null || !url.startsWith(START_URL)) return null;
        String target = url.substring(START_URL.length());
        return jedis.hget(SHORT_URL_HASH_KEY,target);
    }

    public static void main(String[] args) {
        System.out.println(resolutionUrl("http://localhost:8080/1"));
        System.out.println(resolutionUrl("http://localhost:8080/2"));
        System.out.println(resolutionUrl("http://localhost:8080/3"));

        System.out.println(resolutionUrl("2http://localhost:8080/1"));
    }

}

3 列表List

列表是一种线性的有序结构,可以按照元素被推入列表中的顺序来存储元素。这些元素既可以是文字,也可以是二进制,并且元素可重复。

推入弹出

推入:LPUSH、RPUSH、LPUSHX(只对已存在的列表执行推入操作)、RPUSHX

弹出:LPOP、RPOP

将源列表最右端元素弹出,然后将该元素左推入目标列表:RPOPLPUSH

列表

长度:LLEN

获取单个元素:LINDEX

获取元素列表:LRANGE

覆盖:LSET

插入:LINSERT

修剪:LTRIM

删除:LREM

阻塞

BLPOP、BRPOP、BRPOPLPUSH

表 列表数据结构相关命令

3.1 示例

带有阻塞功能的消息队列:一个线程创建一个简单消息接收者,在没有消息时,这个线程会被阻塞,当消息出现时,该接收者将打印这条消息。

public class BlockMessageQueue {

    private final static String BLOCK_MESSAGE_QUEUE_KEY = "block_message_queue";

    public static void main(String[] args) {
        Runnable run1 = () -> {
            System.out.println("具有阻塞功能的消息队列读取");
            System.out.println(RedisPool.getRedis().brpop(5,BLOCK_MESSAGE_QUEUE_KEY));;
            System.out.println("阻塞功能end");
        };

        Runnable run2 = () -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("写入进程2");
            RedisPool.getRedis().lpush(BLOCK_MESSAGE_QUEUE_KEY,"run2");
        };

        Runnable run3 = () -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("写入进程3");
            RedisPool.getRedis().lpush(BLOCK_MESSAGE_QUEUE_KEY,"run3");
        };

        Thread thread1 = new Thread(run1);
        Thread thread2 = new Thread(run2);
        Thread thread3 = new Thread(run3);

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

原文地址:https://blog.csdn.net/qq_25308331/article/details/144297575

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!