rehashindex,是否扩容,值为-1为不扩容
根据key的hash值,去取模sizemask,放到数组里面,如果下标一致的情况下,放入链表,采用头插法,头插法比较快,不用遍历,hashmap是尾插法,防止死链,redis由于是单线程的,不存在这个问题 。
redisObject是封装value的
1、什么时候进行扩容:
1、当没有子进程进行持久化的时候(将数据同步到磁盘的时候),ht[0].used>=ht[0]
2、有子进程持久化的时候,ht[0].userd>=ht[0].size*5
2、怎么扩容
1、当触发扩容的时候,如果扩容的大小和ht[0].size一样,本次不扩容
2、new 一个新的dict ht[1],大小为ht[0].used*2,是2的幂,如果需要查数据的时候,ht[0]和ht[1]都要查询
3、数据进行渐进式迁移,rehashindex=0,代表数据可以迁移
4、数据迁移完成的时候ht[0] =ht[1],ht[1]=null,rehashindex=-1
3、扩容后的数据迁移( 实行渐进式迁移)
1、每次增删改查的时候,如果rehashindex=-1的时候都会迁移
2、定时任务迁移(时间时间驱动servercorn),部分迁移(100个hash桶),默认100ms执行一次
数据类型
1、String 类型,value的底层是SDS
缺点:浪费空间
优点:查询长度速度快
减少修改字符长度带来的内存重分配问题(预分配,SDS长度小于1M会分配长度1M,如果大于1M,就加1M)
如果截取,不马上释放空间,供下次使用
二进制安全,根据len判断字符串是否结束
2、Hash类型,底层是ziplist(压缩列表),数据到达一定数据量用dictht hash表
优点:节省空间,但是可能会拖慢性能
缺点:会引起连锁更新问题,值都是根据偏移量排列好顺序,数据量越大越慢,适合数据量少的场景
3、List类型,底层是quickList
相比较ziplist,有节省空间的同时一定程度上面解决了连锁更新问题,有分段为一个quicknode里面是一个ziplist,即使发生更新,也只是一个node进行重新排序
4、Set类型,底层是intset,如果不是整形就用dictht hash表,数组加链表,如果元素超过配置的512个,就用hashtable
5、Zset类型,底层是ziplist,元素大于128个,或者任意一个member大于64个字节的时候,使用skiplist跳表,最高32层,每次查找用二分查找法,由链表优化而来