目录
环境搭建
依赖
<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层链表,这样,每一个节点的层数都是随机的,新插入节点不会影响其他节点层数,插入节点只需要修改插入节点前后的指针,降低复杂度,
随机算法:产生越高的节点层数,概率越低…….