0
点赞
收藏
分享

微信扫一扫

Java调用redis及redis数据结构

boom莎卡拉卡 2022-01-06 阅读 20
redisjava

目录

环境搭建

依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.73</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.5.3</version>
</dependency>

redis配置

spring:
  application:
    name: Redisdemo
  redis:
    database: 0
    host: 121.40.135.148
    port: 6379
    password: redis123
server:
  port: 8080

序列化

自定义一个序列化转换器:


public class FastJsonSerializer implements RedisSerializer<Object> {
    public static final Charset UTF_8 = Charset.forName("UTF-8");

    public FastJsonSerializer() {
    }

    public byte[] serialize(Object obj) throws SerializationException {
        if (obj == null) {
            return null;
        } else {
            String json = JSON.toJSONString(obj, new SerializerFeature[]{SerializerFeature.WriteClassName});
            return json.getBytes(UTF_8);
        }
    }

    public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes != null && bytes.length > 0) {
            String json = new String(bytes, UTF_8);
            return JSON.parseObject(json, Object.class, new Feature[]{Feature.SupportAutoType});
        } else {
            return null;
        }
    }
}


@Configuration
public class RedisConfiguration {
    public RedisConfiguration() {
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(factory);
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        FastJsonSerializer fastJsonSerializer = new FastJsonSerializer();
        template.setValueSerializer(fastJsonSerializer);
        template.setHashValueSerializer(fastJsonSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

test

@SpringBootTest
class RedisdemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void test() {
        ValueOperations str = redisTemplate.opsForValue();
        HashOperations hash = redisTemplate.opsForHash();
        ListOperations list = redisTemplate.opsForList();
        SetOperations set = redisTemplate.opsForSet();
        ZSetOperations zSet = redisTemplate.opsForZSet();

        str.set("age",20);
        System.out.println("age:"+str.get("age"));
        System.out.println("ince:"+str.increment("age", 1));

        // 添加一个hash集合
        Map<String,String> mp = new HashMap<>();
        mp.put("map1","v1");
        mp.put("map2","v2");
        hash.putAll("map",mp);
        System.out.println("Hash:"+hash.entries("map"));

        //添加一个list集合
        List<String> ls = new ArrayList<>();
        ls.add("l1");
        ls.add("l2");
        list.rightPush("list",ls);
        System.out.println("list:"+list.rightPop("list"));

        //添加一个set
        set.add("set","s1");
        set.add("set","s1");
        System.out.println("set:"+set.members("set"));
        
        //zSet
        zSet.add("people","小明",0);
        zSet.add("people","小红",2);
        zSet.add("people","小白",1);
        System.out.println("zset:"+zSet.rangeByScore("people",0,2));

    }
}

在这里插入图片描述

SDS

字符串的结构是一个sdshdr结构体,包含三个部分,free,len,buf

free:表示未使用的空间
len:表示存储的字符串长度,比如"redis",len=5
buf:存的就是字符串值,采用c语言的字符串以反斜杠0结尾(也占一个空间),可以直接复用c语言的一些函数,无需自己编写

SDS与C字符串:
1、C字符串不记录自身长度,获取长度O(n),SDS中len属性记录长度,O(1)
2、C字符串容易产生缓冲区溢出
3、修改字符串内存分配次数:
C字符串用一个N+1的字符数组保存着N个字符的串,在执行增长字符操作时,需要先通过内存重分配空间大小,忘记会产生缓冲区溢出,缩短操作时,需要通过内存重分配来释放不再使用的空间,忘记会产生内存泄露,SDS采用空间预分配和惰性空间释放优化存在的问题。
4、二进制安全,C字符串不能包含空字符,会误认为结束标志,SDS会以处理二进制的方式来处理buf里面的数组,写入是什么样读取就什么样子

链表

链表结构:

每一个节点是一个 listNode 结构,包含前置节点 prev,后置节点 next,元素值 val, 使用多个 listNode 结构组成一个双端链表。
使用一个 list 结构来持有这个双端链表,操作更方便,list 结构包含:head 头节点,tail 表尾节点,len节点数量。
双端:获取某个点的前置后置节点O(1)
带表头,尾指针:获取表头,尾节点O(1)
带长度计数器:获取数量O(1)

字典

字典:
使用 哈希表 作为底层实现,一个哈希表有多个哈希表节点,节点保存字典中的一个键值对。

哈希表结构:dictht
dictEntry **table :哈希表数组
size:数组大小
sizemark: = size-1,掩码,用于计算索引值
used:哈希表已有节点数量

哈希表节点结构:dicEntry,包含key键,v值,next指向下一个节点

字典结构:dict
dictht ht[2]:哈希表,一般情况只使用ht[0],ht[1]在对ht[0]进行rehash时使用
rehashidx:记录目前rehash进度,没有进行就是-1

添加新键值对时,计算出对应的哈希值和索引值,采用链地址法来解决冲突,单向,因为没有指向尾节点,所以头插
扩展和收缩哈希表的工作通过rehash重新散列,这个rehash分多次,渐进式完成,

跳表

跳表:
有序集合 的底层实现之一,当一个集合元素比较多或者元素成员是比较长的字符串。

跳表 由 有序链表 发展而来,在相邻两个节点增加一个指针,在上一层建立索引,节点为原链表的一半,那么查找就是O(n/2),同样的方式,在上面又建立一层索引,这样当链表很长的时候,这种多层链表可以跳过很多节点,时间为O(logn)

存在问题:插入删除节点时,打乱上下两层链表节点2:1关系,如果重新调整,时间复杂度退化。

解决问题:避免这个问题,不要求上下两层节点个数关系,而是为每个节点随机一个层数(1-32),如果随机是3,就把他链入到1~3层链表,这样,每一个节点的层数都是随机的,新插入节点不会影响其他节点层数,插入节点只需要修改插入节点前后的指针,降低复杂度,

随机算法:产生越高的节点层数,概率越低…….

举报

相关推荐

0 条评论