视频链接:https://www.bilibili.com/video/BV1Rv41177Af/?spm_id_from=333.999.0.0
keys *:当前库所有key。O(N),其中N为数据库包含的键数量。
key pattern:查看当前库的key
scan cursor [MATCH pattern] [COUNT count] [TYPE type]:从数据库中获取一部分键,用户可以通过重复调用SCAN命令来迭代数据库包含的所有键。
SCAN命令、HSCAN命令、SSCAN命令和ZSCAN命令单次执行的复杂度为O(1)
使用这些命令进行一次完整迭代的复杂度则为O(N),其中N为被迭代的元素数量。
scan 0开始,返回下次迭代的游标+本次迭代得到的key
exists key [key ...]:判断key是否在当前库,返回存在key的个数。O(N),其中N为用户给定的键数量。
type key:查看key数据类型。O(1)。
del key [key ...]:删除key。O(N),其中N为被移除键的数量
unlink key [key ...]:非阻塞删除key。O(N),其中N为被移除键的数量
如果待移除的键非常庞大或者数量众多,那么用del命令在服务器执行移除操作的过程中就有可能被阻塞
UNLINK命令与DEL命令一样,都可以用于移除指定的键,但它与DEL命令的区别在于,当用户调用UNLINK命令去移除一个数据库键时,UNLINK只会在数据库中移除对该键的引用(reference),而对键的实际移除操作则会交给后台线程执行,因此UNLINK命令将不会造成服务器阻塞
expire key seconds:为key设置过期时间(单位:秒)。O(1)
pexpire key milliseconds:为key设置过期时间(单位:毫秒)。O(1)
expireat key timestamp:为key设置过期时间(指定过期时间戳-秒)。O(1)。
pexpireat key milliseconds-timestamp:为key设置过期时间(指定过期时间戳-毫秒)。O(1)。
ttl key:查看key的过期时间-秒。-1:永不过期, -2:已过期。O(1)
pttl key:查看key的过期时间-毫秒。-1:永不过期, -2:已过期。O(1)
randomkey:随机地返回一个键。O(1)
sort key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] :对列表元素、集合元素或者有序集合成员进行排序
平均复杂度:O(N*log(N)+M),其中N为被排序元素的数量,而M则为命令返回的元素数量
ASC|DESC:升序/降序
ALPHA:字符串排序
LIMIT:只需要其中一部分排序结果。offset参数用于指定返回结果之前需要跳过的元素数量,而count参数则用于指定需要获取的元素数量。
rename key newkey:修改键的名称。如果用户指定的新键名已经被占用,那么RENAME命令会先移除占用了新键名的那个键,然后再执行改名操作。O(1)。
renamenx key newkey:只会在新键名尚未被占用的情况下进行改名,如果用户指定的新键名已经被占用,那么RENAMENX将放弃执行改名操作。O(1)。
move key db:将一个键从当前数据库移动至目标数据库。当目标数据库存在与给定键同名的键时,MOVE命令将放弃执行移动操作。O(1)
select index: 切换库。提供0-15个数据库,默认0号库。O(1)。
dbsize:查看当前库的key数量。O(1)。
flushdb [ASYNC]:清空当前库。O(N),其中N为被清空数据库包含的键值对数量
如果用户在调用FLUSHDB命令时使用了async选项,那么实际的数据库清空操作将放在后台线程中以异步方式进行,这样FLUSHDB命令就不会再阻塞服务器了。
flushall [ASYNC]:清空全部库。O(N),其中N为被清空的所有数据库包含的键值对总数量。
swapdb index1 index2:接受两个数据库号码作为输入,然后对指定的两个数据库进行互换,最后返回OK作为结果。O(1)。
因为互换数据库这一操作可以通过调整指向数据库的指针来实现,这个过程不需要移动数据库中的任何键值对,所以SWAPDB命令的复杂度是O(1)而不是O(N),
并且执行这个命令也不会导致服务器阻塞
因为redis本身要求获取速度快,那么时间复杂度肯定是O(1),为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对
set key value: 添加键值对。O(1)
set key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]
NX:当数据库中key不存在时,可以将key-value添加到数据库
XX:当数据库中key存在时,可以将key-value添加到数据库,和NX参数互斥。
EX:key的超时秒数
PX:key的超时毫秒数,和EX互斥
KEEPTTL: 加上后修改key,不改变key过期时间?
get key:查询键对应的值。O(1)
append key value:将给定的value追加到原值的末尾。O(N),其中N为新追加内容的长度。
strlen key:获取值的长度。O(1)
setnx key value:只有key不存在时,设置key的值
incr key:将key中储存的数字值加1。O(1)
decr key:将key中储存的数字值减1。O(1)
incrby key increment:将key中储存的值增加自定义步长。O(1)
decrby key increment:将key中储存的值减少自定义步长。O(1)
mset key value [key value ...]:同时设置多个key-value。O(N)
mget key [key ...]:同时获取一个或多个value。O(N)
msetnx key value [key value ...]:同时设置1个或多个key-value对,当前仅当所有给定的key都不存在。O(N)
getrange key start end:获得值的范围,闭区间。end可越界。O(N)
setrange key offset value:用value覆盖key所储存的字符串值,从起始位置开始(索引从0开始)。O(N)
setex key seconds value:设置键值的同时,设置过期时间(单位:秒)
getset key value:以旧换新,设置了新值的同时,获得旧值。O(1)
lpush/rpush key element [element ...]:从左边/右边插入一个或多个值。O(N),其中N为被推入列表的元素数量
lpushx/rpushx key element [element ...]:只会在列表已经存在的情况下,将元素推入列表左端。O(N),其中N为被推入列表的元素数量??
lpop/rpop key:从左边/右边吐出一个值。键在值在,键光值亡。O(1)
rpoplpush source destination:从source列表右边吐出一个值,插到destination的左边。O(1)
lrange key start stop:按照索引下标获得元素(从左到右, -1是最右边value索引)。O(N),其中N为给定列表的长度。
lindex key index:按照索引下标获得元素(从左到右)。O(N),其中N为给定列表的长度。
llen key:获得列表的长度。O(1)
linsert key BEFORE|AFTER pivot element: 在首次出现pivot值前/后插入element值。O(N),其中N为给定列表的长度。
lrem key count element:从左边删除count个element(从左到右),0-全部。O(N),其中N为给定列表的长度
lset key index element:将列表key下标为index的值替换成element。O(N),其中N为给定列表的长度。
ltrim key start stop:保留给定范围之内的元素,移除给定索引范围之外的所有元素。O(N),其中N为给定列表的长度
typedf struct inset{
uint32_t encoding;//编码方式 默认 INSET_ENC_INT16
// 有三种,INTSET_ENC_INT16、INSET_ENC_INT32和INSET_ENC_INT64三种,分别对应不同的范围。
// Redis为了尽可能地节省内存,会根据插入数据的大小选择不一样的类型来进行存储。
uint32_t length;//集合元素个数
// 记录了保存数据的数组contents中共有多少个元素,这样获取个数的时间复杂度就是O(1)。
int8_t contents[];// 元素类型并不一定是ini8_t类型
//真正存储数据的地方,数组是按照从小到大有序排列的,并且不包含任何重复项
}
sadd key member [member ...]: 将一个或多个member元素加入到集合key中,已经存在的member元素将被忽略。O(N),其中N为用户给定的元素数量。
smembers key:取出该集合的所有值。O(N),其中N为集合包含的元素数量。
sismember key value:判断集合key是否含有value值,1-有, 0-没有。O(1)
scard key:返回该集合的元素个数。O(1)
srem key member [member ...]:删除集合中的元素member。O(N),其中N为用户给定的元素数量。
spop key [count]:随机从集合中取出一个/count个值,并从集合中删除。O(N),其中N为被返回的元素数量。
srandmember key [count]: 随机从该集合中取出一个/count个值,不会从该集合中删除。O(N),其中N为被返回的元素数量。
smove source destination member:把member值从source集合移动到destination集合。O(1)
sinter key [key ...]:一个key时,查看集合key中的所有元素。多个key时,取多个集合的交集。O(N*M),其中N为给定集合的数量,而M则是所有给定集合当中,包含元素最少的那个集合的大小。
sinterstore destination key [key ...]:把给定集合的交集计算结果存储到指定的键里面。键已经存在的情况下自动覆盖已有的键。O(N*M),其中N为给定集合的数量,而M则是所有给定集合当中,包含元素最少的那个集合的大小。
sunion key [key ...]:一个key时,查看集合key中的所有元素。多个key时,取多个集合的并集。O(N),其中N为所有给定集合包含的元素数量总和。O(N),其中N为所有给定集合包含的元素数量总和
sunionstore destination key [key ...]:把给定集合的并集计算结果存储到指定的键中,并在键已经存在的情况下自动覆盖已有的键。O(N),其中N为所有给定集合包含的元素数量总和
sdiff key [key ...]:一个key时,查看集合key中的所有元素。多个key时,按顺序取集合的差集。O(N),其中N为所有给定集合包含的元素数量总和。
eg.sdiff key1 key2 key3:先计算key1和key2的差集,再计算key1和key2差集和key3的差集。
sdiffstore destination key [key ...]:把给定集合之间的差集计算结果存储到指定的键中,并在键已经存在的情况下自动覆盖已有的键。O(N),其中N为所有给定集合包含的元素数量总和。
hset key field value [field value ...]:给key集合中的field键赋值value。O(N)??
hget key field:从key集合filed取出value。O(1)
hmset key field value [field value ...]:批量设置hash值。O(N),其中N为被设置的字段数量。
hmget key field [field ...]:批量获取field1,field2值。O(N),其中N为被设置的字段数量。
hexists key field:查看key中,field是否存在。O(1)
hkeys key:列出key中所有field。O(N),其中N为散列包含的字段数量
hvals key:列出key中所有value。O(N),其中N为散列包含的字段数量
hincrby key field increment:为hash表key中的field值加上增量。O(1)
hincrbyfloat key field increment:为hash表key中的field值加上浮点增量。O(1)
hsetnx key field value:将hash表key中的field设为value,当且仅当field不存在。O(1)
hgetall key:查看key所有field和value。O(N),其中N为散列包含的字段数量
hstrlen key field:获取给定字段值的字节长度。O(1)
hdel key field [field ...]:删除散列中的指定字段及其相关联的值。O(N),其中N为被设置的字段数量。??
hlen key:获取给定散列包含的字段数量。O(1)。
zadd key [NX|XX] [CH] [INCR] score member [score member ...]: 将一个或多个member元素及其score值加入到有序集key中
XX:在给定XX选项的情况下,ZADD命令只会对给定成员当中已经存在于有序集合的成员进行更新,而那些不存在于有序集合的给定成员则会被忽略。
NX:在给定NX选项的情况下,ZADD命令只会把给定成员当中不存在于有序集合的成员添加到有序集合里面,而那些已经存在于有序集合中的给定成员则会被忽略。
CH:用户可以通过给定CH选项,让ZADD命令返回被修改(changed)成员的数量作为返回值。“被修改成员”指的是新添加到有序集合的成员,以及分值被更新了的成员
O(M*log(N)),其中M为给定成员的数量,而N则为有序集合包含的成员数量。
zrange key start stop [WITHSCORES]:返回有序集key中,下标在start和stop之间的元素。带WITHSCORES,可以让分数一起和值返回到结果集。O(log (N) + M),其中N为有序集合包含的成员数量,而M则为命令返回的成员数量。
zrevrange key start stop [WITHSCORES]:倒序返回有序集key中,下标在start和stop之间的元素。O(log (N) + M),其中N为有序集合包含的成员数量,而M则为命令返回的成员数量。
zrangebyscore key min max [WITHSCORES] [LIMIT offset count]:返回有序集key中,所有score介于min和max之间(闭区间)的成员。O(log (N) +M),其中N为有序集合包含的成员数量,而M则为命令返回的成员数量
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]:同上,从大到小。O(log (N) +M),其中N为有序集合包含的成员数量,而M则为命令返回的成员数量
zincrby key increment member:为元素member的score加上增量increment。O(log (N)),其中N为有序集合包含的成员数量。
zrem key member [member ...]:删除该集合下,指定的元素(member)。O(M*log(N)),其中M为给定成员的数量,N为有序集合包含的成员数量。
zcount key min max:统计该集合,分数区间的元素个数。O(log (N)),其中N为有序集合包含的成员数量
zrank key member:返回该值在集合中的排名,排名从0开始。O(log (N)),其中N为有序集合包含的成员数量。
zrevrank key member:返回该值在集合中的倒序排名。O(log (N)),其中N为有序集合包含的成员数量。
zscore key member:获取与给定成员相关联的分值。O(1)
zcard key:取得有序集合的基数,即有序集合包含的成员数量。O(1)
zremrangebyrank key start stop:从升序排列的有序集合中移除位于指定排名范围内的成员,然后返回被移除成员的数量。O(log (N) + M),其中N为有序集合包含的成员数量,M为被移除的成员数量
zremrangebyscore key min max:从有序集合中移除位于指定分值范围内的成员,并在移除操作执行完毕返回被移除成员的数量。O(log (N) + M),其中N为有序集合包含的成员数量,M为被移除成员的数量。
zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]:并集。O(N*log(N)),其中N为所有给定有序集合的成员总数量。
zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]:交集。O(N*log(N)*M),其中N为所有给定有序集合中,基数最小的那个有序集合的基数,而M则是给定有序集合的数量
zrangebylex key min max [LIMIT offset count]:返回指定字典序范围内的成员。O(log (N) + M),其中N为有序集合包含的元素数量,而M则为命令返回的成员数量。
zrevrangebylex key max min [LIMIT offset count]:返回指定字典序范围内的成员。O(log (N) + M),其中N为有序集合包含的元素数量,而M则为命令返回的成员数量。
zlexcount key min max:统计位于字典序指定范围内的成员数量。O(log (N)),其中N为有序集合包含的成员数量。
zremrangebylex key min max:移除位于字典序指定范围内的成员。O(log (N) + M),其中N为有序集合包含的成员数量,M为被移除成员的数量
zpopmax key [count]:弹出分值最高的成员。O(N),其中N为命令移除的元素数量。
zpopmin key [count]:弹出分值最低的成员。O(N),其中N为命令移除的元素数量。
bzpopmax key [key ...] timeout:阻塞式最大元素弹出操作。O(N),其中N为用户给定的有序集合数量
bzpopmin key [key ...] timeout:阻塞式最小元素弹出操作。O(N),其中N为用户给定的有序集合数量
subscribe channel1
打开另一个客户端,给channel1发布消息
publish channel1 hello
返回的结果是订阅者数量:打开第一个客户端,就可以看到发送的消息unsubscribe [channel [channel ...]]:退订给定的频道。
subscribe channel [channel ...]:订阅一个或多个频道。
pubsub subcommand [argument [argument ...]]:查看订阅与发布系统状态。
punsubscribe [pattern [pattern ...]]:退订所有给定模式的频道。
publish channel message:将信息发送到指定的频道。
psubscribe pattern [pattern ...]:订阅一个或多个符合给定模式的频道
setbit key offset value:设置Bitmaps中某个偏移量的值(0或1)。offset:偏移量从0开始。返回二进制位被设置之前的旧值。O(1)
getbit key offset:获取Bitmaps中某个偏移量的值。获取键的第offset位的值(从0开始算)。访问未设置的offset也返回0。O(1)
bitcount key [start end]:统计位图中值为1的二进制位数量。start参数和end这两个参数是用来指定字节偏移量而不是二进制位偏移量的。O(N),其中N为被统计字节的数量。
eg. K1 【01000001 01000000 00000000 00100001】,对应【0,1,2,3】
bitcount K1 1 2:统计下标1,2字节组中bit=1的个数,即01000000 00000000 =》 1
bitcount K1 1 3:统计下标1,2,3字节组中bit=1的个数,即01000000 00000000 00100001 =》3
bitcount K1 0 -2:统计下标0到下标倒数第2,字节组中bit=1的个数,即01000001 01000000 00000000 =》3
bitop operation destkey key [key ...]:bitop是一个复合操作, 它可以做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中。O(N),其中N为查找涉及的字节数量。。
bitpos key bit [start] [end]:在位图中查找第一个被设置为指定值的二进制位,并返回这个二进制位的偏移量。O(N),其中N为查找涉及的字节数量
bitfield key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]:在位图中的任意区域(field)存储指定长度的整数值,并对这些整数值执行加法或减法操作。O(N),其中N为用户给定的子命令数量。
bitfield k2 set u8 0 123 set i32 20 10086:从偏移量0开始,设置一个8位长无符号整数值123。从偏移量20开始,设置一个32位长有符号整数值10086。
pfadd key element [element ...]:添加指定元素到 HyperLogLog 中。如果执行命令后key估计的近似基数发生变化,则返回1,否则返回0。O(N),其中N为用户给定的元素数量
pfcount key [key ...]:计算key的近似基数,可以计算多个key。O(N),其中N为用户给定的HyperLogLog数量
pfmerge destkey sourcekey [sourcekey ...]:将一个或多个key合并后的结果存储在另一个key中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得。O(N),其中N为用户给定的HyperLogLog数量
geoadd key longitude latitude member [longitude latitude member ...]:添加地理位置(经度,纬度,名称)
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
两极无法直接添加,一般会下载城市数据,直接通过程序一次性导入。
有效的经度从 -180 度到 180 度。有效的纬度从 -85.05112878 度到 85.05112878 度。
当坐标位置超出指定范围时,该命令将会返回一个错误。已经添加的数据,是无法再次往里面添加的。
geopos key member [member ...]:获得指定地区的坐标值。O(log (N)*M),其中N为位置集合目前包含的位置数量,而M则为用户给定的位置数量
geopos china:city beijing
geodist key member1 member2 [m|km|ft|mi]: 获取两个位置之间的直线距离。O(log (N)),其中N为位置集合目前包含的位置数量
geodist china:city beijing shanghai km
单位:m 表示单位为米[默认值]。km 表示单位为千米。mi 表示单位为英里。ft 表示单位为英尺。
georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]:以给定的经纬度为中心,找出某一半径内的元素。经度 纬度 距离 单位
O(N),其中N为命令实施范围查找时检查的位置数量。
WITHDIST:这些位置与中心点之间的距离
WITHHCOORD:返回被匹配位置的坐标
ASC|DESC:排序查找结果
COUNT:限制命令获取的位置数量
georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]:查找指定位置半径范围内的其他位置
O(N),其中N为命令实施范围查找时检查的位置数量。
geohash key member [member ...]:获取指定位置的Geohash值。O(N),其中N为用户给定的位置数量
xadd key ID field value [field value ...]:追加新元素到流的末尾。O(log (N)),其中N为流目前包含的元素数量。
如果给定的流不存在,那么Redis会先创建一个空白的流,然后将给定的元素追加到流中
ID:流元素的ID由毫秒时间(millisecond)和顺序编号(sequcen number)两部分组成
使用UNIX时间戳表示的毫秒时间用于标识与元素相关联的时间
以0为起始值的顺序编号则用于区分同一时间内产生的多个不同元素
XADD s1 1100000000000-12345 k1 v1。元素ID的毫秒时间部分为1100000000000,而顺序编号部分则为12345。Redis将把包含键值对k1和v1的新元素追加到流s1的末尾
XADD s1 1000000000000 k1 v1。用户在输入流ID的时候,除了可以给出带有毫秒时间和顺序编号的完整流ID之外,还可以给出只包含毫秒时间的不完整流ID:在这种情况下,Redis会自动将ID的顺序编号部分设置为0
不允许使用相同的ID,同时要求新元素的ID必须比流中所有已有元素的ID都要大
*:当用户将符号*用作id参数的值时,Redis将自动为新添加的元素生成一个可用的新ID。
maxlen:XADD命令还提供了MAXLEN选项,让用户可以在添加新元素的同时删除旧元素,以此来限制流的长度。xadd key * maxlen 3 1 a 2 b 3 c
xtrim key MAXLEN [~] count:对流进行修剪。返回被移除元素的数量作为结果。O(log (N) + M),其中N为执行修剪操作前流包含的元素数量,而M则为被移除元素的数量。
stream最开头的count个元素将被移除
参数~的意思是,用户不是真的需要精确的count个项目。它可以多几十个条目,但决不能少于count个。通过使用这个参数,仅当我们移除整个节点的时候才执行修整。这使得命令更高效,而且这也是我们通常想要的。
xdel key ID [ID ...]:移除指定元素。O(log (N)*M),其中N为流包含的元素数量,而M则为被移除元素的数量。
xlen key:获取流包含的元素数量。O(1)
xrange key start end [COUNT count]:用于读取给定ID范围内的消息数据,并可以设置返回数据的条数。O(log (N) + M),其中N为流包含的元素数量,而M则为命令返回的元素数量。
start:开始消息ID,指定具体值或通过“-”特殊符号来表示最小ID。
end:结束消息ID,指定具体值或通过“+”特殊符号来表示最大ID。
xrevrange key end start [COUNT count]:访问流中元素。O(log (N) + M),其中N为流包含的元素数量,而M则为命令返回的元素数量。
xrevrange命令与xrange用法完全一致,唯一区别是返回数据的顺序为消息ID的递减序,正好与xrange返回的数据顺序相反。
xgroup [CREATE key groupname id-or-$] [SETID key groupname id-or-$] [DESTROY key groupname] [DELCONSUMER key groupname consumername] [HELP]:用于队列的消费组管理,包含对消费组的创建、删除、修改等操作
O(N+ M),其中N为消费者组被删除时,仍处于“待处理”状态的消息数量,而M则是该组属下消费者的数量。
xreadgroup GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]:用于从消费组中可靠地消费n条消息,如果指定的消费者不存在,则创建之。
对于用户给定的每个流,从流中获取消息的复杂度为O(log (N) + M),其中N为流包含的消息数量,而M则为被获取消息的数量。因此对于用户给定的I个流,获取这些流消息的总复杂度为O((log (N) + M)*I)。
xread [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...]:用于从Stream队列中读取N条消息,一般用作遍历队列中的消息。
对于用户给定的每个流,获取流元素的复杂度为O(log (N) + M),其中N为流包含的元素数量,M为被获取的元素数量。因此对于用户给定的I个流,获取流元素的总复杂度为O((log (N) + M)*I)
xpending key group [start end count] [consumer]:显示待处理消息的相关信息
执行XPENDING stream group格式的XPENDING的复杂度为O(N),其中N为消费者组目前拥有的消费者数量;执行带有start、stop和count参数的XPENDING命令的复杂度为O(log (N) + M),其中N为消费者组目前拥有的待处理消息总数量,而M则是命令返回的消息数量;执行带有consumer参数的XPENDING命令的复杂度为O(log(N) +M),其中N为该消费者目前拥有的待处理消息数量,而M则为命令返回的消息数量。
xack key group ID [ID ...]:将消息标记为“已处理”。O(N),其中N为用户给定的消息ID数量
xclaim key group consumer min-idle-time ID [ID ...] [IDLE ms] [TIME ms-unix-time] [RETRYCOUNT count] [force] [JUSTID]:转移消息的归属权
O(N),其中N为用户给定的消息ID数量。
xinfo [CONSUMERS key groupname] [GROUPS key] [STREAM key] [HELP]:查看流和消费者组的相关信息
XINFO CONSUMERS命令的复杂度为O(N),其中N为给定消费者组的消费者数量;XINFO GROUPS命令的复杂度为O(M),其中M为给定流属下的消费者组数量;XINFO STREAM命令的复杂度为O(1)
都是根据先进先出规则来淘汰旧元素的
If you are using Redis 6, install go-redis/v8:
go get github.com/go-redis/redis/v8
If you are using Redis 7, install go-redis/v9:
go get github.com/go-redis/redis/v9
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
func PingRedis(rdb *redis.Client) {
cmd := rdb.Ping(ctx)
err := cmd.Err()
if err != nil {
panic(err)
}
fmt.Println(cmd.Val())
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
PingRedis(rdb)
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
// set
func SetString(rdb *redis.Client, key string, value string, ex time.Duration) bool {
cmd := rdb.Set(ctx, key, value, ex)
if cmd.Err() != nil {
fmt.Println("设置失败:", cmd.Err())
return false
}
return true
}
// get
func GetString(rdb *redis.Client, key string) string {
cmd := rdb.Get(ctx, key)
if cmd.Err() != nil {
fmt.Println("获取string值失败:", cmd.Err())
return ""
}
return cmd.Val()
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
setFlag := SetString(rdb, "k1", "value1", 120*time.Second)
fmt.Println(setFlag) // true
value := GetString(rdb, "k1")
fmt.Println(value) // value1
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
// rpush
func RpushList(rdb *redis.Client, key string, values ...interface{}) bool {
cmd := rdb.RPush(ctx, key, values)
if cmd.Err() != nil {
fmt.Println("Lpush失败:", cmd.Err())
return false
}
return true
}
// lrange
func LrangeList(rdb *redis.Client, key string, start int64, end int64) []string {
cmd := rdb.LRange(ctx, key, start, end)
if cmd.Err() != nil {
fmt.Println("Lrange失败:", cmd.Err())
return []string{}
}
return cmd.Val()
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
LpushFlag := RpushList(rdb, "k2", "golang", "php", "python", 10001, 10086)
fmt.Println(LpushFlag)
ListValue := LrangeList(rdb, "k2", 0, -1)
fmt.Println(ListValue)
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
// sadd
func SAddSet(rdb *redis.Client, key string, members ...interface{}) bool {
cmd := rdb.SAdd(ctx, key, members)
if cmd.Err() != nil {
fmt.Println("SAdd失败:", cmd.Err())
return false
}
return true
}
// smembers
func SMembersSet(rdb *redis.Client, key string) []string {
cmd := rdb.SMembers(ctx, key)
if cmd.Err() != nil {
fmt.Println("获取集合成员失败:", cmd.Err())
return []string{}
}
return cmd.Val()
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
SaddFlag := SAddSet(rdb, "k3", "golang", "php", "python", 10001, 10086, "golang", 10001, "python")
fmt.Println(SaddFlag)
Smembers := SMembersSet(rdb, "k3")
fmt.Println(Smembers)
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
// hset
func HSetHash(rdb *redis.Client, key string, values ...interface{}) bool {
cmd := rdb.HSet(ctx, key, values)
if cmd.Err() != nil {
fmt.Println("hset失败:", cmd.Err())
return false
}
return true
}
// hkeys
func HKeysHash(rdb *redis.Client, key string) []string {
cmd := rdb.HKeys(ctx, key)
if cmd.Err() != nil {
fmt.Println("获取hash key失败:", cmd.Err())
return []string{}
}
return cmd.Val()
}
// hvals
func HValsHash(rdb *redis.Client, key string) []string {
cmd := rdb.HVals(ctx, key)
if cmd.Err() != nil {
fmt.Println("获取hash value失败:", cmd.Err())
return []string{}
}
return cmd.Val()
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
HSetFlag := HSetHash(rdb, "k4", "golang", 1, "php", 2, "python", 3, "python", 4)
fmt.Println(HSetFlag)
HashKeys := HKeysHash(rdb, "k4")
fmt.Println(HashKeys)
HashValues := HValsHash(rdb, "k4")
fmt.Println(HashValues)
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func ConnectClient() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "172.29.170.39:6379",
Password: "123456",
DB: 0,
})
return rdb
}
// zadd
func ZAddZset(rdb *redis.Client, key string, members ...*redis.Z) bool {
cmd := rdb.ZAdd(ctx, key, members...)
if cmd.Err() != nil {
fmt.Println("zadd失败:", cmd.Err())
return false
}
return true
}
// zrange
func ZrangeWithScoreZset(rdb *redis.Client, key string, start interface{}, stop interface{}) []redis.Z {
z := redis.ZRangeArgs{
Key: key,
Start: start,
Stop: stop,
}
cmd := rdb.ZRangeArgsWithScores(ctx, z)
if cmd.Err() != nil {
fmt.Println("获取zset数据失败:", cmd.Err())
return []redis.Z{}
}
return cmd.Val()
}
// do
func ZsetDo(rdb *redis.Client, args ...interface{}) interface{} {
cmd := rdb.Do(ctx, args...)
if cmd.Err() != nil {
fmt.Println("do err:", cmd.Err())
return false
}
return cmd.Val()
}
func main() {
rdb := ConnectClient()
defer rdb.Close()
members1 := redis.Z{Score: 100, Member: "php"}
members2 := redis.Z{Score: 200, Member: "golang"}
members3 := redis.Z{Score: 300, Member: "python"}
ZaddFlag := ZAddZset(rdb, "k5", &members1, &members2, &members3)
fmt.Println(ZaddFlag)
ZsetVals := ZrangeWithScoreZset(rdb, "k5", 0, -1)
fmt.Println(ZsetVals)
ZRes := ZsetDo(rdb, "zcount", "k5", 100, 200)
fmt.Println(ZRes)
}
from redis import StrictRedis
# 连接
client = StrictRedis("172.26.108.198", password="123456")
resp = client.ping()
if resp == True:
print("连接成功")
# string操作
resp = client.set("k1", "2023-01-12", 120)
if resp == True:
print("k1设置成功")
resp = client.get("k1")
if resp==None:
print("key不存在")
else:
print(resp.decode())
# hash操作
res = client.delete("k2")
resp = client.hset("k2", "name", "lily", {"age":18, "gender":"女"})
if resp == True:
print("k2设置成功")
resp = client.hkeys("k2")
if resp==None:
print("key不存在")
else:
print([i.decode() for i in resp])
resp = client.hvals("k2")
if resp==None:
print("key不存在")
else:
print([i.decode() for i in resp])
import redis.clients.jedis.Jedis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JedisTest {
public static void main(String[] args) {
// 连接到redis
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.auth("redis");
String pong = jedis.ping();
System.out.println("连接成功:"+pong);
// set
jedis.set("k1", "v1");
jedis.set("k2", "v2");
jedis.set("k3", "v3");
// keys *
Set<String> keys = jedis.keys("*");
System.out.println(keys.size());
System.out.println(keys);
// exists
System.out.println(jedis.exists("k1"));
// ttl
System.out.println(jedis.ttl("k1"));
// get key
System.out.println(jedis.get("k1"));
// mset
jedis.mset("str1","v1","str2","v2","str3","v3");
// mget
System.out.println(jedis.mget("str1","str2","str3"));
// lset
jedis.lpush("mylist", "hello", "world", "!");
jedis.rpush("mylist", "hello", "world", "~");
// lrange
List<String> list = jedis.lrange("mylist",0,-1);
System.out.println(list);
// del
jedis.del("mylist");
// sadd
jedis.sadd("orders", "order01");
jedis.sadd("orders", "order02");
jedis.sadd("orders", "order03");
jedis.sadd("orders", "order04");
// smembers
Set<String> smembers = jedis.smembers("orders");
System.out.println(smembers);
// srem
jedis.srem("orders", "order02");
Set<String> smembers2 = jedis.smembers("orders");
System.out.println(smembers2);
// hset
jedis.hset("hash1","userName","lisi");
// hget
System.out.println(jedis.hget("hash1","userName"));
// hmset
Map<String,String> map = new HashMap<String,String>();
map.put("tel","123456");
map.put("addr","example");
map.put("email","abc@163.com");
jedis.hmset("hash2",map);
// hmget
List<String> result = jedis.hmget("hash2", "tel","email");
System.out.println(result);
// hgetAll
Map<String, String>mp = jedis.hgetAll("hash2");
System.out.println(mp);
// zadd
jedis.zadd("zset01", 100d, "z3");
jedis.zadd("zset01", 90d, "l4");
jedis.zadd("zset01", 80d, "w5");
jedis.zadd("zset01", 70d, "z6");
// zrange
Set<String> zrange = jedis.zrange("zset01", 0, -1);
System.out.println(zrange);
// 断开连接
jedis.close();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>springboot-test-redis</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.X集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
server.port=8080
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis数据库索引(默认为0)
spring.redis.database= 0
# 连接超时时间(毫秒)
spring.redis.timeout=1800000
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=20
# 最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=5
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
# 连接密码
spring.redis.password=redis
RedisConfig
package com.example.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
//key序列化方式
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
//value hashmap序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
MyConfig
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({RedisConfig.class})
public class MyConfig {
}
MainApplication
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication()
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
RedisController
package com.example.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/redisTest")
public class RedisController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping
public String testRedis() {
//设置值到redis
redisTemplate.opsForValue().set("name","lucky");
//从redis获取值
String name = (String)redisTemplate.opsForValue().get("name");
System.out.println(name);
return name;
}
}
页面访问
// client-1
watch k1
multi
set k1 value1
set k2 value2
get k1
get k2
// client-2
set k1 v1
set k2 v2
// client-1
exec
// 结果:nil 事务内命令没执行
// client-1或client2
get k1 // v1
get k2 // v2
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。