redis基础总结(数据类型)

chatgpt/2023/10/4 8:48:09

Redis十大数据类型

String

String 是redis最基本数据类型,一个key对应一个value. String类型是二进制安全的,意思是Redis的string类型可以包含任何数据,比如jpg图片或者序列化的对象;
String类型是最基本的数据类型,一个redis中字符串value最多是512M;
String类型在redis底层数据结构是SDS(简单动态字符串);
简单应用: incr可以实现 某篇文章点赞量 等功能

常用命令:

set key value  //设置指定key值
get key //获取指定key值
getrange key start end //返回key中字符串的子字符 例如: getrange  key1 0 -1; 返回value ;getrange key1 0 1 ; 返回v
getset key value //将指定key的值设置为value,并返回key的旧值;
getbit key offset //对key所存储的字符串值,获取指定偏移量上的位(bit)
mget key1 key2 key3 //获取所有(一个或多个给定key的值)
setbit key offset value//对key所储存的字符串值,设置或清楚指定偏移量上的位
setex key seconds value //将值value关联到key,并将key的过期时间设置为seconds(以s为单位)
setnx key value //只有在key不存在时 设置key的值
setrange key offset value//用value参数覆写给定key所存储的字符串值,从偏移量offset开始;
strlen key //返回key所存储的字符串值的长度
mset key value key1 value1 key2 value2. . .//同时设置一个或多个k-v对
msetnx key value[key value . . . ] //同时设置一个或多个key-value对,当且仅当所有给定key都不存在
psetex key milliseconds value // 和setex命令相似 , 但是它以毫秒为单位设置过期时间
incr key //将key中存储的数字值增1;
incrby key increment//将key所存储的值加上给定的增量值(incrment)
decr key;//将key中存储的数字值减一
decrby key decrement//将key所存储的值减去给定的减量值(decrment)
append key value//如果key已经存在并且是一个字符串,append命令将value追加到key原来的值的末尾

SDS

Redis底层是用C来实现的,C语言中没有java里面的string类型,只能靠自身的cha[]来实现,字符串在C语言中的存储方式,想要获取[redis]的长度,需要从头开始遍历,直到遇到'\0' 为止,所以,redis 没有直接使用C语言的字符串标识,而是自己构建了一种名为简单动态字符串SDS(simple dynamic string)的抽象类型,并将SDS作为Redis的默认字符串;

struct _attribute_((_packed_)) sdshdr8{uint8_t len;unit8_t alloc;unsigned char flags;char buf[];
};
struct _attribute_((_packed_)) sdshdr16{uint16_t len;unit16_t alloc;unsigned char flags;char buf[];
};

sds与char对比:

SDS类型RedisObject内部对应3大物理编码:

int: 保存long类型的64位有符号整数,最小值-2^63; 最大值是2^63-1; 默认值是0L; 最多19位数字;另外 只有整数才会使用int,如果是浮点数,Redis内部其实先将浮点数转化为字符串值,然后在保存;
当执行 set k1 123 时:
当字符串键值内容可以有那个一个64位有符号整形来表示时,Redis会将键值转化为long类型进行存储,此时即对应OBJ_ENCODING_INT 编码类型; Redis启动会预先建立1W个分别存储0到9999的redisObject变量作为共享对象,折旧意味着如果set字符串的键值在0~10000之间的化,则可以直接使用共享对象,而不需要在建立新对象,此时键值不占空间;

embstr(embedded string):嵌入式的字符串; 代表embstr格式的sds(simple dynamic string 简单动态字符串),保存长度小于44字节的字符串;
当执行set k1 abc 时:
对于长度小于44的字符串,Redi对键值采用OBJ_EnCODING_EMBSTR方式,从内存结构上讲,即字符串sds结构体与对应的Redisobject对象分配在同一块连续的内存空间;
raw:长度超过44字节的字符串
当字符串长度大于44时,redis则会将键值的内部编码方式改为OBJ_ENCODING_RAW格式,这与embstr编码方式不同之处在于,此时动态字符串sds的内存与依赖的redisObject的内存不连续了;
另外,对于embstr,由于其实现是只读的,如果对其进行修改,都是先转为raw在进行修改,因此,只要是修改embstr对象,修改后的对象一定是raw的,无论格式是否到了44字节;判断不出来,就取最大Raw

获取编码格式命令:object encoding key

总结:

List

Redis list 是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边).它的底层实际是个双端链表,最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素). 主要功能有push/pop等,一般用在栈、队列、消息队列等场景。left、right都可以插入添加;如果键不存在,创建新的链表;如果键已存在,新增内容;如果值全移除,对应的键也就消失了。

常用命令:

blpop key1 [key2] timeout//移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
brpop key1 [key2] timeout//移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
lpush/rpush/lrange //在左/右/指定位置  新增元素
lpop/rpop //弹出最左 /最后侧一个元素
lindex key index //按照索引下标获得元素(从上到下) ( lindex  list2 3  获取list2  下标是3的元素)
llen //获取列表中元素的个数
lrem key  n v1 ; //删除列表中N个值等于v1 的元素
ltrim key 开始index  结束index;//截取指定范围的值后再赋值给key
rpoplpush list2 list 3 //移除list2列表的最后一个元素,并将该元素加到list3列表 并返回
lset key index value// 修改列表指定index的值 为value
linsert key before/after 已有值  插入的新值;//在list某个已有值的前后再添加具体值(linsert list3 before oracle mysql  在list3中 oracle前插入mysql)

简单应用: 关注多个公众号 文章推送(例如: 公众号 1 和公众号2 发布了两篇文章 分别是11和22; 账号A关注了这两个公众号,只要他们发布新文章,就会安装进A的list :lpush likearticle:A-id 11 12 ; A 查看自己订阅号的全部文章,类似于分页 :lrange likearticle:A-id 0 9)

Redis List 底层数据结构

在Redis3.0之前,list采用的底层数据结构是ziplist(压缩列表)+linkedList(双向链表)
然而在高版本的redis中底层数据结构是quicklist(替换了ziplist+linkedList),而quicklist也用到了ziplist;quicklist就是一个链表,而链表中的每个元素又是一个压缩列表;
比较早版本的redis中,list底层两种实现:
1.当列表对象中元素的长度比较小或者数量比较少的时候,采用ziplist存储
2.当列表中元素的长度比较大或者数量比较多 则会转而使用linkedlist存储;
优缺点:
1.ziplist的优点是内存紧凑,访问效率高,缺点是更新效率低,并且数据量较大时,可能导致大量内存复制;
2.linkedlist的优点是 节点修改效率高,但是需要额外的内存开销,并且节点较多时,会产生大量内存碎片;
综上所述,在redis3.2之后,list的底层实现变为快速列表 quicklist;

quicklist

redis6中, quicklist实际上是ziplist和linkedList的混合体,它将linkedlist按段切分,每一段用ziplist来紧凑存储,多个ziplist之间使用双向指针串接起来,*zl指向一个ziplist,一个ziplist可以存放多个元素.
简单来说,一个 quicklist 就是一个链表,而链表中的每个元素又是一个 ziplist。这种设计减少了数据插入时内存空间的重新分配,以及内存数据的拷贝。同时,quicklist 限制了每个节点上 ziplist 的大小,一旦一个 ziplist 过大,就会采用新增 quicklist 节点的方法。
不过,又因为 quicklist 使用 quicklistNode 结构指向每个 ziplist,无疑增加了内存开销。为了减少内存开销,并进一步避免 ziplist 连锁更新问题,Redis 在 5.0 版本中,就设计实现了 listpack 结构。listpack 结构沿用了 ziplist 紧凑型的内存布局,把每个元素都紧挨着放置。

redis7中用listpack代替了ziplist ; 所以,在redis7中 quicklist是listpack和linkedlist的结合体;

ziplist和listpack

ziplist

ziplist结构如下:

privious_entry_length,encoding长度都可以根据编码方式推算,真正变化的是content,而content长度记录在encoding里 ,因此entry的长度就知道了。entry总长度 = privious_entry_length字节数+encoding字节数+content字节数.
链表在内存中,一般是不连续的,遍历相对比较慢,而ziplist可以很好的解决这个问题。如果知道了当前的起始地址,因为entry是连续的,entry后一定是另一个entry,想知道下一个entry的地址,只要将当前的起始地址加上当前entry总长度。如果还想遍历下一个entry,只要继续同样的操作。
从 ziplist 的设计不足出发,ziplist 的最大特点,就是它被设计成一种内存紧凑型的数据结构,占用一块连续的内存空间,以达到节省内存的目的。但是,在计算机系统中,任何一个设计都是有利有弊的。对于 ziplist 来说,这个道理同样成立。虽然 ziplist 节省了内存开销,可它也存在两个设计代价:一是不能保存过多的元素,否则访问性能会降低;二是不能保存过大的元素,否则容易导致内存重新分配,甚至可能引发连锁更新的问题。所谓的连锁更新,简单来说,就是 ziplist 中的每一项都要被重新分配内存空间,造成 ziplist 的性能降低.
连锁更新:
压缩列表每个节点正因为需要保存前一个节点的长度字段,就会有连锁更新的隐患
第一步:现在假设一个压缩列表中有多个连续的、长度在 250~253 之间的节点,如下图:

因为这些节点长度值小于 254 字节,所以 prevlen 属性需要用 1 字节的空间来保存这个长度值.
第二步:这时,如果将一个长度大于等于 254 字节的新节点加入到压缩列表的表头节点,即新节点将成为entry1的前置节点,如下图:


因为entry1节点的prevlen属性只有1个字节大小,无法保存新节点的长度,此时就需要对压缩列表的空间重分配操作并将entry1节点的prevlen 属性从原来的 1 字节大小扩展为 5 字节大小。
第三步:连续更新问题出现


entry1节点原本的长度在250~253之间,因为刚才的扩展空间,此时entry1节点的长度就大于等于254,因此原本entry2节点保存entry1节点的 prevlen属性也必须从1字节扩展至5字节大小。entry1节点影响entry2节点,entry2节点影响entry3节点......一直持续到结尾。这种在特殊情况下产生的连续多次空间扩展操作就叫做「连锁更新」

listpack

listpack 是 Redis 设计用来取代掉 ziplist 的数据结构,它通过每个节点记录自己的长度且放在节点的尾部,来彻底解决掉了 ziplist 存在的连锁更新的问题.
listpack由四部分组成,如下图:

total bytes: 为整个listpack的空间大小,占用4个字节,每个listpack最多占用4294967295Bytes(2^32-1).
number-elements: listpack中的元素个数,即Entry的个数占用2个字节
element-1~element-N : 具体的元素
listpack-end-byte:为listpack结束标志,占用一个字节,内容为0xff


总结:
zipList为了节省内存 采用了紧凑的连续存储,ziplist是一个双向链表,可以再时间复杂度为O(1)下从头部或者尾部进行pop或push; 缺点是:新增或更新元素可能会出现连锁更新现象,不能保存过多的元素否则查询效率会降低,数量小核内容小的情况下可以使用;
和ziplist列表类似,listpack列表项也包含了元数据信息和数据本身,不过为了避免ziplist引起连锁更新问题,listpack中每个列表项不在像ziplist列表项那样保存其前一个列表的长度.

Hash

Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)
常用命令:

hset/hget/hmset/hmget/hgetall/hdel //插入/获取/批量插入/批量获取/获取全部/删除
hlen //后续某个key内的全部数量
hexits key filed //key里面是否存在filed的值
hkeys/hvals //hkeys hash2 (返回hash2下所有filed), hvals hash2(返回hash2下所有value)
hincrby/hincrbyfloat key file number//指定key filed 增加number  浮点数用float
hsetnx  key file value // 不存在赋值返回1; 存在无效返回0;

简单应用场景: 简单购物车设计

购物车新增商品 - hset shopcar:uid1024 334488 1
新增商品一 hset shopcar:uid1024 334477 1
增加商品数量 一 hincrby shopcar:uid1024 3344771
商品总数 一 hlen shopcar:uid 1024
全部选择一 hgetall shopcar:uid1024

redis6中hash底层是ziplist+hashtable; redis7中 用listpack替代了ziplist;
默认情况向 hash对象保存的键值对数量小宇512个,并且所有键值对的键和值的字符串长度都小宇64byte时用ziplist(redis7用listpack),反之用hashtable; ziplist/listpack 可以升级到hashtable,但是不可以反过来降级; 一旦从ziplist/listpack升级到hashtable ,hash类型就会一直使用hashtable进行保存,而不能转回去; 在节省内存空间方面hashtable没有ziplist/listpack 高效.
这两个参数也可以通过设置来改变:
hash-max-ziplist-entries/hash-max-listpack-entries: 使用ziplist/listpack 保存时哈希集合中的最大元素个数;
hash-max-ziplist-value/hash-max-listpack-value:使用ziplist/listpack 保存时哈希集合中单个元素的最大长度

Set

Redis的set是String类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据,集合对象的编码可以是intset或者hashtable.
redis中set集合是通过hashtable实现的,所以添加,删除,查找的复杂度 都是O(1);集合中最大成员数为2^32-1(每个集合可存储40多亿个成员);
常用命令:

sadd key member[member ...] //新增
smembers key //遍历集合中的所有元素
sismember key member //判断元素是否存在集合中
srem key member [member ...] //删除集合中元素
scard //scard set1  获取set1集合中元素个数
srandmember key [数字N] //从集合中随机展现N个元素,元素不删除 如果超过最大值,则全部取出
spop key [数字N] //从集合中随机弹出元素,出一个删一个
smove key1 key2 v1;//将key1 中的v1 赋值给key2
//========= 集合运算  A - abc12   B-123ax
sidff key [key...] // 属于A但不属于B的元素构成的集合
sunion key [key...] //属于A或者属于B的元素合并后的集合
sinter key [key...] //属于A同时也属于B的共同拥有的元素构成的集合
sintercard numkeys key [key...] [limit n] //numkeys 表示几个去重的集合 命令如 sintercard 2 key1 key2 --返回key1 和key2 两个集合交集的元素个数; sintercard 3 key1 key2 key3 limit  4 --返回key 1 2 3 交集元素个数 如果超过4 则返回4  否则返回真实个数

简单应用:

//=====微信抽奖小程序:
sadd key userID//新增用户ID参与抽奖 
scard key//显示已经有多少人参与活动
//抽取N个人中奖  : 
srandmember key N //不删除抽取 ;   
spop key N //删除抽取
//=======微信朋友圈点赞查看同赞朋友:
sadd pub:msgID  userID1 userID2//user1 user2点赞
srem pub:msgID userID2 //user2取消点赞
smembers pub:msgID //展现点赞的用户
scard pub:msgID //获取点赞的用户数
sismember pub:msgID userID3//判断user3 是否点过赞

Redis用intset或者hashTable存储set,如果元素都是整数类型,就用intset存储.如果不是整数类型,就用hashtable(数组+链表的结构来存储).key就是元素的值,value为null
集合元素都是long类型,并且元素个数<=set-max-intset-entries 编码就是intset,反之就是hashtable;

ZSet

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复,zset集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32 - 1;
常用命令:

zadd key score member [score member] //添加元素
zrange key start stop [withscores] //按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素
zrevrange  key start stop [withscores] //按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素
zrangebyscore key min max [withscores] [limit offset count] //获取指定分数范围的元素
(是不包含的意思;  zrangebyscore zset1 (60 90 withscores (返回60到90之间的key和value 不包含60)  
zscore key member //获取元素分数 
zcard zset1//获取zset1元素个数
zcount zset1 60 90 //获取分数区间内元素个数
zrank // 获取value在zset中的下标位置  zrank zset1 v2   (获取zset1中v2的下标)
zscore zset1 v1 // 按照值获取对应分数
zrem key 某score下对应的value值//删除 
zincrby key increment member //增加某个元素的分数
zcount key min max //获取指定分数范围内的元素个数
zmpop //从键名列表中的第一个非空排序集中弹出一个或多个元素,他们是成员分数对(key value score)
zrank key values //获取下标值
zrevrank key values //逆序获取下标值

应用场景:

//=====根据商品销售对商品进行排序显示
//===定义商品销售排行榜(sorted set集合),key为goods:sellsort,分数为商品销售数量
zadd goods:sellsort 9 1001 15 1002 // 商品编号1001 的销量是9,编号1002的销量是15
zincrby goods:sellsort 2 1001 //有一个客户买了2件商品1001,商品编号1001销量加2
zrange goods:sellsort 0 9 withscores //求商品销量前10名

当有序集合中包含的元素数量超过服务器属性 server.zset_max_ziplist_entries 的值(默认值为 128 ),或者有序集合中新添加元素的 member 的长度大于服务器属性server.zset_max_ziplist_value 的值(默认值为 64 )时,redis会使用跳跃表作为有序集合的底层实现。否则会使用ziplist作为有序集合的底层实现(redis7用listpack实现)

跳表

对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个数据,也只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高O(N)

对单链表进行升维,也叫空间换时间.如下:


从这个例子里,我们看出,加来一层索引之后,查找一个结点需要遍历的结点个数减少了,也就是说查找效率提高了.
skiplist 是一种以空间换取时间的结构.由于链表无法进行二分查找,因此借鉴数据库索引的思想,提取出链表中关键节点(索引),先在关键节点上查找,在进入下层链表查找,提取多层关键节点,就形成了skiplist. 但是 由于索引也需要占据一定空间,所以,索引添加的越多,空间占用的越多

总结:
跳表=链表+多级索引
跳表的时间复杂度O(logn) ;空间复杂度O(N)
优点:跳表是一个最典型的空间换时间解决方案,而且只有在数据量较大的情况下才能体现出来优势。而且应该是读多写少的情况下才能使用,所以它的适用范围应该还是比较有限的
缺点:维护成本相对要高,在单链表中,一旦定位好要插入的位置,插入结点的时间复杂度是很低的,就是O(1) ,但是,新增或者删除时需要把所有索引都更新一遍,为了保证原始链表中数据的有序性,我们需要先找到要动作的位置,这个查找操作就会比较耗时最后在新增和删除的过程中的更新,时间复杂度也是O(log n)

GEO

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,包括:添加地理位置的坐标。获取地理位置的坐标。计算两个位置之间的距离。根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
常用命令

geoadd key longitude latitude member [longitude latitude member ...]//添加经纬度坐标
geopos key member [member ...]//从给定的key里返回所有的指定名称(member)的位置,不存在的返回null
geohash key member [member...] //获取一个或多个元素的geohash值
geodist key member1 member2 [m|km|ft|mi] // 用于返回两个给定位置之间的距离
georadius  //以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUS city 116.418017 39.914402 10 km withdist withcoord count 10 withhash desc //WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。WITHCOORD: 将位置元素的经度和维度也一并返回。WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大 ; COUNT 限定返回的记录数。
georadiusbymember city 天安门 10 km withdist withcoord count 10 withhash//找出位于指定范围内的元素,中心点是由给定的位置元素決定

简单应用:

//=========地图附近的酒店推送
@Service
@Slf4j
public class GeoService
{public static final String CITY ="city";@Autowiredprivate RedisTemplate redisTemplate;
//新增地点public String geoAdd(){Map<String, Point> map= new HashMap<>();map.put("天安门",new Point(116.403963,39.915119));map.put("故宫",new Point(116.403414 ,39.924091));map.put("长城" ,new Point(116.024067,40.362639));redisTemplate.opsForGeo().add(CITY,map);return map.toString();}//获取经纬度坐标public Point position(String member) {List<Point> list= this.redisTemplate.opsForGeo().position(CITY,member);return list.get(0);}//geohash算法生成的base32编码值public String hash(String member) {List<String> list= this.redisTemplate.opsForGeo().hash(CITY,member);return list.get(0);}//获取两个给定位置之间的距离public Distance distance(String member1, String member2) {Distance distance= this.redisTemplate.opsForGeo().distance(CITY,member1,member2, RedisGeoCommands.DistanceUnit.KILOMETERS);return distance;}
//通过经度,纬度查找附近的,北京王府井位置116.418017,39.914402public GeoResults radiusByxy() {Circle circle = new Circle(116.418017, 39.914402, Metrics.KILOMETERS.getMultiplier());//返回50条RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(50);GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults= this.redisTemplate.opsForGeo().radius(CITY,circle, args);return geoResults;}public GeoResults radiusByMember() {//通过地方查找附近String member="天安门";//返回50条RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(50);//半径10公里内Distance distance=new Distance(10, Metrics.KILOMETERS);GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults= this.redisTemplate.opsForGeo().radius(CITY,member, distance,args);return geoResults;}
}

HyperLogLog

HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素
Redis使用了214=16384个桶,误差为0.81%,精度相当高。Redis使用一个long型哈希值的前14个比特用来确定桶编号,剩下的50个比特用来做基数估计。而2^6=64,所以只需要用6个比特表示下标值,在一般情况下,
一个HLL数据结构占用内存的大小为16384*6/8=12kB,Redis将这种情况称为密集(dense)存储。
常用命令:

pfadd key element [element...] //添加指定元素到hyperloglog中
pfcount key [key...] 返回给定hyperloglog 的技术估算值
pfmerge destkey sourcekey [sourcekey...]//将多个hyperloglog合并为一个hyperloglog

demo

//=====获取去重后某个页面的访问量====
//=========
@Service
@Slf4j
public class HyperLogLogService
{@Resourceprivate RedisTemplate redisTemplate;/*** 模拟后台有用户点击首页,每个用户来自不同ip地址*/@PostConstructpublic void init(){log.info("------模拟后台有用户点击首页,每个用户来自不同ip地址");new Thread(() -> {String ip = null;for (int i = 1; i <=200; i++) {Random r = new Random();ip = r.nextInt(256) + "." + r.nextInt(256) + "." + r.nextInt(256) + "." + r.nextInt(256);Long hll = redisTemplate.opsForHyperLogLog().add("hll", ip);log.info("ip={},该ip地址访问首页的次数={}",ip,hll);//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }}},"t1").start();}@ApiOperation("获得IP去重后的首页访问量")@RequestMapping(value = "/uv",method = RequestMethod.GET)public long uv(){return redisTemplate.opsForHyperLogLog().size("hll");}
}

bigmap

由0和1状态表现的二进制位的bit数组


说明:用String类型作为底层数据结构实现的一种统计二值状态的数据类型.位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们称之为一个索引)。
Bitmap支持的最大位数是232位,它可以极大的节约存储空间,使用512M内存就可以存储多达42.9亿的字节信息(232 = 4294967296)
常用命令:

setbit key offset value //设置 setbit zhangsan 1 1 ; setbit zhangsan 4 1; 设置张三1号 4号打卡  
getbit key offset //
strlen key //获取占用的字节,超过8位后自己按照8位一组-byte在扩容
bitcount key start end //返回指定key中[start end]中为1的数量   bitcount zhangsan  ; 返回2 
bitop operation destkey key//对不同的二进制存储数据进行位运算(AND、OR、NOT、XOR)   (bittop and destkey 20200808 20200809  返回连续两天签到的bigmap ; bitcount destkey  返回2 )

bitfield

通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。

Stream

Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。

参考文档:https://blog.csdn.net/weixin_45735834/article/details/126559660

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-5313227.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

RISC-V公测平台发布 · 第一个WEB Server “Hello RISC-V world!”

RISC-V公测平台Web Server地址&#xff1a;http://175.8.161.253:8081 一、前言 Web Server是互联网应用的基础设施&#xff0c;无论是用户访问网站&#xff0c;还是后端服务提供商和开发者构建各种应用程序&#xff0c;Web Server都在其中扮演着至关重要的角色。 显而易见…

Linux6.22 ansible playbook role——LNMP

文章目录 计算机系统5G云计算第一章 LINUX ansible playbook 延申一、用ansible playbook完成yum式安装集中式LNMP二、用 ansible playbook的role 角色完成 LNMP 的部署1.nginx2.mysql3.php计算机系统 5G云计算 第一章 LINUX ansible playbook 延申 一、用ansible playbook完…

服务器 Docker Alist挂载到本地磁盘(Mac版)夸克网盘

1.服务器下载alist 默认有docker环境 docker pull xhofe/alist2.生成容器 -v /home/alist:/opt/alist/data 这段意思是alist中的数据映射到docker 主机的文件夹&#xff0c;/home/alist就是我主机的文件夹&#xff0c;这个文件夹必须先创建 docker run -d --restartalways…

playwright自动化项目搭建

具备功能 关键技术&#xff1a; pylaywright测试库pytest单元测试框架pytest-playwright插件 非关键技术&#xff1a; pytest-html插件pytest-rerunfailures插件seldom 测试框架 实现功能&#xff1a; 元素定位与操作分离失败自动截图并保存到HTML报告失败重跑可配置不同…

12、springboot自定义banner

springboot自定义banner ▲ 控制Banner信息是否显示及在哪里显示&#xff1a; 在application.properties这个配置文件里面进行以下的属性设置&#xff1a;spring.main.banner-mode 属性进行设置&#xff0c;该属性支持如下3个属性值&#xff1a;- console&#xff1a;在Spring…

文本生成模型评估方法

“”" 好的&#xff0c;我来通俗易懂地介绍一下这几个指标&#xff0c;并给出一些例子。1. Rouge 指标Rouge 是一组用于自动文本摘要评估的指标&#xff0c;经常用于自然语言处理中。Rouge 包括三种常用的指标&#xff1a;Rouge-1、Rouge-2 和 Rouge-L&#xff0c;它们的…

4090Ti被取消,NVIDIA还要推出新“甜品卡“

不知不觉距离 NVIDIA RTX 40 系显卡发布已快一年&#xff0c;4090 到 4060 从旗舰到甜品也都差不多了。 不过每个男孩子都想要的礼物 - RTX 4090 Ti &#xff0c;至今仅在春晚发布。 从核心架构上来看&#xff0c;RTX 4090 上的 AD 102-300 也确实不是完全体。 仅拥有144组 S…

Stable Diffusion 文字生成图片如何写提示词

Stable Diffusion是一种基于神经网络的技术&#xff0c;通过输入提示词来生成相应的图片。为了获得高质量的图片输出&#xff0c;您需要选择合适的提示词&#xff0c;并确保它们能够激发模型的想象力和创造力。 以下是一些编写提示词的建议&#xff1a; 确定主题&#xff1a;…
推荐文章