《redis开发与运维》1-3章

目录

介绍

一、常用命令

二、事务

三、客户端


介绍

redis将所有数据存放在内存中(纯内存访问,100ns),还可以将内存的数据利用快照和日志的形式保存到硬盘上。官方给出的读写性能是10w/s,使用C语言实现的单线程架构,预防了多线程可能产生的竞争问题(避免线程切换和竞态产生的消耗)。使用I/O多路复用,非阻塞I/O。

使用场景:缓存,提供键过期功能、内存溢出淘汰策略;排行榜,提供列表和有序集合;计数系统,O(1)的计数功能;社交网络;消息队列,提供简单的发布订阅和阻塞队列功能。

不适用场景:数据量太大,冷数据,浪费内存。

redis版本号中第二位如果是奇数则表示非稳定版本,redis3.0增加了redis cluster分布式实现。

内部编码

每种数据结构底层有自己的内部编码实现,而且都有两种以上,例如list有linkedlist和ziplist两种实现,ziplist比较节省内存,但是元素比较多的情况下性能有所下降。redis会在合适的场景选择合适的内部编码。objects encoding key可以查看内部编码。

一、常用命令

通用命令,不分数据结构:

命令

说明

复杂度

keys *

查看所有键

O(n),遍历所有键

dbsize

键总数

O(1),内置键总数变量

exists key

键是否存在,存在返回1

del key [key ...]

删除key,返回删除成功的个数

expire key seconds

添加键过期时间,单位是秒

ttl key

查看键过期时间,返回-1没设置过期时间,-2键不存在

type key

key的数据结构类型

String

键是字符串类型,值可以是字符串(string, json, xml)、数字(整数, 浮点数)、二进制(图片, 音频, 视频),值最大不超过512MB。

命令

说明

复杂度

set key value [ex seconds] [px milliseconds] [nx|xx]

设置键值对

ex seconds:键秒级过期时间

px million:毫秒级过期时间

nx:键不存在时设置成功

xx:键存在时更新,不存在不成功

O(1)

setex key seconds value

和 set key ex seconds 一样

O(1)

setnx key value

和 set key value nx一样,多个客户端执行setnx时只有一个会成功,可以作为分布式锁的实现方案

O(1)

get key

O(1)

mset key value [key value ...]

批量设置,节省网络传输时间

O(k),k = key个数

mget key [key ...]

批量获取

同上

incr key

decr key,自减

incrby/decrby key increment,自增/自减指定数

incrbyfloat key increment,自增指定浮点数

对value自增,返回自增后的结构;value不是整数返回error;键不存在时按值=0自增,返回1

O(1)

不常用命令

append key value

字符串尾部追加值

O(1)

strlen key

value长度

O(1)

getset key value

set新值,返回原值

O(1)

setrange key offset value

设置指定位置的字符,offset是下标

O(1)

getrange key start end

获取部分字符串,左闭右闭

O(n),n = 字符串长度

内部编码:根据值的类型和长度决定,int(8字节长整型),embstr(<=39字节的字符串),raw(>39字节的字符串)。

Hash

value本身又是一个键值对结构,key value(field value)。

命令

说明

复杂度

hset key field value

设置键值对

O(1)

hget key field

获得value

O(1)

hmset key field value [field value ...]

批量设置field value

O(k),k = field个数

hmget key field [field ...]

批量获得value

O(k)

hgetall key

获得field+value

O(n),n = field总数

hkeys key

获得所有field

O(n),n = field总数

hvals key

获得所有value

O(n),n = field总数

hdel key field [field]

删除一个或多个field

O(k),k = field个数

hlen key

计算field个数

O(1)

hexists key field

field是否存在

O(1)

内部编码:当key和value都小于一定值时,用ziplist,结构更加紧凑,节省内存。不满足使用ziplist的条件时,用hashtable,读写复杂度O(1),ziplist不满足性能要求。

List

存储多个有序字符串,可以重复,支持索引范围内获取元素。redis中可以对列表两端插入、弹出,可以充当栈和队列的角色。

命令

说明

复杂度

lpush/rpush key value [value ...]

从左边/右边添加元素

O(k),k = key个数

linsert key before|after pivot value

向列表指定元素(pivot)前|后插入value

O(n),pivot到表头/尾的距离

lrange key start end

(lrange key 0 -1:从左到右获取全部元素)

获取指定范围内的元素

左闭右闭

从左到右下标0 ~ N-1

从右到左下边-1 ~ -N

O(s + n),start的偏移和范围的长度

lindex key index

获取指定下标的value

O(1)

llen key

列表长度

O(1)

lpop/rpop key

弹出最左侧/右侧元素

O(1)

lrem key count value

删除值=value的元素

count>0,从左到右删除最多count个

count<0,从右到左删除最多|count|个

count=0,删除所有

O(n),n = 列表长度

ltrim key start end

只保留列表[start end]

O(n),n = 修剪的元素个数

lset key index index newValue

修改指定下标的元素

O(n),n = 索引偏移量

blpop/brpop key [key ...] timeout

阻塞式弹出,超时时间内客户端等待

timeout = 0时一直等待

O(1)

内部编码:元素较少时ziplist,较多时用linkedlist链表。

使用场景:消息队列(lpush和brpop可实现阻塞队列)、文章列表

Set

存储多个字符串元素,不能重复,无序,不能通过索引下标获取元素。redis支持集合内的增删改查、集合间的并交差。

命令

说明

复杂度

sadd key element [element ...]

添加元素

O(k),k = 元素个数

srem key element [element ...]

删除元素

同上

scard key

计算元素个数

O(1)

sismember key element

元素是否在集合中

O(1)

srandmember key [count默认1]

随机返回指定个数元素

O(count)

spop key

随机弹出元素

O(1)

smembers key

获取全部元素

O(n),n = 元素总数

集合间操作

sinter key [key ...]

交集

O(m*k),m=集合个数,k=元素最少的集合元素个数

sunion key [key ...]

并集

O(k),多个集合元素个数和

sdiff key [key ...]

差集

同上

sinterstore/sunionstore/sdiffstore destination key [key ...]

保存并交差的结果

同上

内部编码:intset整数集合(元素个数较少且都是整数),hashtable。

使用场景:标签、社交场景,每个用户感兴趣的标签不同,通过集合可以得到喜欢同一个标签的用户,和用户共同喜好的标签。

Zset

集合元素不能重复,但可以排序。不是和list一样通过下标,它给每个元素设置一个score作为排序的依据。

命令

说明

复杂度

zadd key score member [score member ...]

添加成员和分数

nx:member不存在时添加成功

xx:member存在时操作成功,用于更新

incr:对score自增

O(log(n))

zcard key

计算成员个数

zscore key member

成员分数

zrank/zrerank key member

返回成员排名,从0开始排,zrank从低到高排,zrerank从高到低

zrem key member [member ...]

删除成员

zincrby key increment member

给member增加分数increment

zrange/zrerange key start end [withscores]

返回指定排名范围的成员

[start, end]

zrangebyscore/zrerangebyscore key min max [withscores]

返回指定分数范围内的成员

zcount key min max

返回指定分数范围成员个数

集合间操作

zinterstore destination numkeys key [key ...] [weights weight [weight ...] [aggregate sum|min|max]

交集

destination保存到这个键

numkeys做交集的键个数

weights每个键的权重,默认1,权重*score是最后的score

aggregate:得到的交集,成员的分值取sum、min还是max,默认sum

zunionstore destination numkeys key [key ...] [weights weight [weight ...] [aggregate sum|min|max]

并集

内部编码:ziplist(默认元素小于128个,且元素值小于64B),skiplist跳表。

使用场景:排行榜系统。

其他

Bitmaps

Bitmaps本省并不是一个数据结构,实际上还是字符串,但是它可以对字符串的位进行操作,可以看做一个以位为单位的数组,每个单元值存储0和1。

命令

说明

复杂度

setbit key offset value

设置值

getbit key offset

获取键的第offset位的值

bitcount key [start end]

获取指定范围内值为1的个数

start, end代表起始和结束字节数

bitop op destkey key [key ...]

bitmaps间的运算

op可取and(交)、or(并)、not(非)、xor(异或)

bitpos key targetBit [start] [end]

计算第一个值=targetBit的偏移量

使用场景:统计独立用户数量(例如某个用户id是否访问过网站,在id对应的位上置0或1,不适用访问用户很稀疏的情况,这样每个用户id占一位,但是需要开辟的位很多,中间都是0)。

HyperLogLog

HyperLogLog是一种基数算法,可以用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等。

命令

说明

复杂度

pfadd key element [element ...]

添加元素

pfcount key [key ...]

计算独立用户数

pfmerge destkey sourcekey [sourcekey ...]

求并集

HyperLogLog计数存在0.81%的误差率。

GEO

地理位置信息。

命令

说明

geoadd key longitude latitude member [...]

添加经、纬度、成员

geoadd cities 116.28 39.55 beijing

geopos key member [member ...]

获得成员经纬度

gepdist key member1 member2 [unit单位]

获得成员间的地理位置距离

georadius key longitude latitude radiusm|km|ft|mi []

以一个地理位置为中心,算出指定半径内的其他地理信息位置

geohash key member [member ...]

将二维经纬度转换为一维字符串

二、事务

pipeline

Lua

三、客户端

客户端与服务端通信协议

这里的客户端指的是编程语言中的Redis客户端。客户端和服务端之间的通信协议是在TCP协议之上构建的,Redis制定了RESP(Redis序列化协议)实现客户端和服务端的正常交互。

客户端将命令封装成符合RESP的格式,发送一条命令的格式:

// set hello world
// 格式:
*参数数量
$参数1字节数
参数1
$参数2字节数
参数2
...
  
// 示例
*3
$3
SET
$5
hello
$5
world
// 实际格式
*3\r\n$3\r\nSET\r\n$5hello\r\n$5\r\n$5\r\nworld\r\n
// redis.clients.jedis.Protocol#sendCommand

private static void sendCommand(RedisOutputStream os, byte[] command, byte[]... args) {
        try {
            os.write((byte)42);
            os.writeIntCrLf(args.length + 1);
            os.write((byte)36);
            os.writeIntCrLf(command.length);
            os.write(command);
            os.writeCrLf();
            byte[][] var3 = args;
            int var4 = args.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                byte[] arg = var3[var5];
                os.write((byte)36);
                os.writeIntCrLf(arg.length);
                os.write(arg);
                os.writeCrLf();
            }

        } catch (IOException var7) {
            throw new JedisConnectionException(var7);
        }
    }

redis-cli按照RESP进行结果解析,我们只能看到最终的结果,服务端返回的结果的格式:

// RESP格式在返回结果前加相应代码
状态回复:+   // 例如客户端发送set, 服务端回复+OK
整数回复::   // 客户端执行incr, 回复:1
字符串回复:$   // get hello, 回复$5 world
多个字符串:*   // mget  

Java客户端Jedis

使用方法:

// 直连方式, 生产环境一般使用连接池JedisPool管理Jedis连接, 预先初始化好Jedis连接, 每次使用时从Jedis连接池中借用, 不需要每次创建TCP连接, 还能限制Jedis对象个数 
Jedis jedis = new Jedis("127.0.0.1", port);  // Redis实例的ip和端口

// 方法与redis-cli对应, redis.clients.jedis.JedisCommands

Jedis提供连接池JedisPool,通过GenericObjecPoolConfig设置JedsiPool属性:

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 常用的有:设置最大连接数为默认值的5倍 
poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5); 
// 设置最大空闲连接数为默认值的3倍 
poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3); 
// 设置最小空闲连接数为默认值的2倍 
poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2); 
// 设置开启jmx功能
poolConfig.setJmxEnabled(true);
// 设置连接池没有连接后客户端的最大等待时间(单位为毫秒) 
poolConfig.setMaxWaitMillis(3000);

// 初始化Jedis连接池
JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);

lettuce API

提供三种API

  • sync(同步),RedisCommands,在所有命令调用之后立即返回结果

  • async(异步),RedisAsyncCommands,所有方法执行返回的结果都是RedisFuture

  • reactive(反应式),RedisReactiveCommands

待补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值