REDIS - 安装和基本命令(一)

本文详述了在CentOS7系统中安装Redis-6.2.1的过程,包括安装依赖、编译与安装步骤。还介绍了Redis的基本命令、配置、数据类型及其操作,如键值存储、发布订阅、过期策略等。此外,讨论了Redis的原子性、内存管理和安全设置,以及如何通过配置文件调整服务行为。
摘要由CSDN通过智能技术生成

本文首发于我的个人网站:http://riun.xyz/


本文介绍了redis在linux系统下的安装和使用时的基本命令、基本配置。

以下基于redis-6.2.1版本,系统为centos7 64位

官方文档:http://www.redis.cn/documentation.html

大纲:fErnoD.md.jpg

1、安装

安装C 语言的编译环境

yum install centos-release-scl scl-utils-build

yum install -y devtoolset-8-toolchain

scl enable devtoolset-8 bash

测试 gcc版本

gcc --version

fErnoD.md.jpg

安装redis

cd /opt
wget http://download.redis.io/releases/redis-6.2.1.tar.gz
tar -zxvf redis-6.2.1.tar.gz
cd redis-6.2.1/
make
make install

默认安装目录:/usr/local/bin

进入后查看ls

redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何

redis-check-aof:修复有问题的AOF文件,rdb和aof后面讲

redis-check-dump:修复有问题的dump.rdb文件

redis-sentinel:Redis集群使用

redis-server:Redis服务器启动命令

redis-cli:客户端,操作入口

以上命令均可在任意目录下执行。

2、运行

备份redis.conf

cp /opt/redis-6.2.1/redis.conf /myredis/

修改启动模式:

vim /myredis/redis.conf

查找/daemonize

将daemonize no 改为daemonize yes

redis会在后台运行,此时redis将一直运行,除非手动kill该进程。同时将进程pid号写入至redis.conf选项pidfile设置的文件中,默认会生成在/var/run/redis.pid,也可以通过pidfile来指定pid文件生成的位置。

而采用no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。

执行:redis-server /myredis/redis.conf

查看:ps -ef | grep redis

(当前目录/usr/local/bin)

客户端连接:redis-cli

(指定端口redis-cli -p6380)

退出客户端:在redis命令行界面执行exit (只退出当前客户端,不关闭redis服务)

关闭服务:redis-cli shutdown (在当前目录下执行,关闭后redis服务就关闭了)

也可以在redis客户端里执行shutdown(和上面一个效果,关了就是把redis服务关了,就连不上了)

3、使用

3.1、系统命令

默认16个数据库,默认使用0号库。

select 来切换数据库。 select 1

所有库同样密码

dbsize查看当前数据库key数量。

flushdb清空当前库。

flushall通杀全部库。

Redis是单线程+多了IO复用技术。

3.2、基本命令

查找命令:http://www.redis.cn/commands.html

key

keys * 查看当前库所有key

keys *str 匹配某个特征的key,比如keys *me

keys str* 匹配某个特征的key,比如keys na*

fErnoD.md.jpg

exists key 判断某个key是否存在 存在返回1,不存在返回0

type key 查看key是什么类型

del key1 key2 删除一个或多个key

unlink key 根据value选择非阻塞删除(仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。)

expire key 10 设置key 10秒钟之后过期

ttl key 查看key的过期时间,-1 永不过期,-2已过期(不存在的key都会返回-2)。

String

String类型意味着value是String类型的,之后的Set Hash都是对value来说的。key一定是String的。

String的数据结构为简单动态字符串(Simple Dynamic String ,SDS),是可以修改的字符串。内部结构类似于ArrayList,采用预分配冗余空间的方式减少内存频繁分配。

当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。

String类型是二进制安全的,意味着它可以包含任何数据,比如jpg图片或者序列化对象。

一个Redis中字符串value最多可以是512M。

set key value

set key value nx|xx ex|px

nx:当key不存在时,可以添加

xx:当key存在时,可以添加,与nx互斥

ex:key的超时秒数(过期时间,秒为单位)

px:key的超市毫秒数(过期时间,毫秒为单位),与ex互斥

注:这些都只在一个库内有效。

fErnoD.md.jpg

①在不同库中设置key1 nx均为OK,说明不同库nx不会生效。

②在同一个库中,一个使用nx,一个不使用nx均OK,说明nx只对nx生效,对普通的set key value不生效。

③在同一个库set key1 value nx后者返回nil,说明设置失败,证明了nx为当key不存在时,才可以添加

其实nx命令是用来做分布式锁的,更简洁全面的写法是:set lock 123456 ex 60 nx

在设置nx值的同时添加上过期时间(保证原子性,一条命令执行完加锁的工作)

fErnoD.md.jpg

假设某个业务操作,多机中只能有一个同时在执行。比如某个商品的销量num,假设他存在redis中,一个机器拿到num进行销量的添加时,其他机器就不能拿着添加了。

假如①是一个服务器,操作redis时先set lock 123456 ex 60 nx添加了锁,然后他就可以做某些业务操作,比如给num添加到100。

然后②是另一台服务器,尝试set lock 1234567 ex 60 nx加锁时,发现返回nil,加锁失败,于是休息重试。等到①完成操作然后删除锁时,②就可以顺利获取到锁了,于是他就可以进行业务操作,比如给num添加了50,这时他拿到的一定是别人加过的,而不是正在加的值。能保证值的准确。

上述只是小例子,实际业务中基于redis的分布式锁还要注意:**1、**value值必须唯一,防止高并发下的误删,可以使用uuid。**2、**加锁操作原子了,解锁操作也必须原子,使用uuid后,解锁时势必要判断uuid和当前锁的uuid是否一样,判断一致后才能del解锁,这样两步的操作在高并发环境下也有可能出问题,为了防止误删(判断之后key的过期时间刚好到了,其他机器拿到锁,准备进行操作,然后本机执行了del操作,删除了其他机器的锁。),可以使用lua脚本进行解锁(判断+删key)。lua脚本能保证原子的原因是使用lua脚本将判断和删除的动作写成一个脚本,然后使用redis执行这个脚本,由于redis是单线程,所以执行脚本的时候一定会执行完,其他命令才能执行,也就是说脚本中判断+删key的操作一定会串行执行完毕后,其他命令才能执行,才会获取到锁。


原子性

所谓原子操作是指不会被线程调度机制打断的操作;

这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch(切换到另一个线程)。

(1)在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间。

(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。

Redis单命令的原子性主要得益于Redis的单线程。


get key 查询key对应的value

append key value 将value追加到原key对应value的末尾,返回字符串长度。(中文,两个字符长度)

strlen key 获取key长度

setnx key value 当Key不存在时,设置key的值。不能跟过期时间,不建议使用。

incr key 将key对应的value增加1,只能对数字值操作,操作非数字值会报错;但如果操作的key不存在,则自动将key和value 1添加进去。fErnoD.md.jpg

decr key 减一,和上面大致一样,若Key不存在则value为-1。

incrby / decrby key 步长,将key增加、减少对应步长。

mset key1 value1 key2 value2 (不能加nx px等)

mget key1 key2

msetnx key1 value1 key2 value2 同时设置多个key value,当且仅当所有key都不存在时设置成功。原子性,有一个失败则都失败。

getrange key indexBegin indexEnd 指定index获取值,前闭后闭

setrange key indexBegin value 从indeBegin开始,覆盖value。

setex key time value 设置key value并设置过期时间,秒为单位。

getset key value 获取旧值,并设置新值。不存在key时,返回nil,但是新值已经设置进去。

List

单键多值,字符串列表,按照插入顺序排序。可以自定义添加到列表的头部(左边)或尾部(右边)。

底层双向链表,对两端操作性能较好,对中间元素需要通过下标操作性能较差。

数据结构:快速链表quickList,元素较少时会使用一块连续的内存储存,这个结构是ziplist,即压缩列表(所有元素紧挨着储存)。当数据量较多时才改为quicklist。因为普通链表附加指针空间太大,会浪费空间(pre、next指针)

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

ziplist可以理解为数组,但是它的每个元素空间可以不同(数组每隔位置大小一样)

lpush key value1 value2 value3 从左边插入一个值,返回插入后list的长度

rpush key value1 value2 value3 从右边插入一个值

lpop key 从左边弹出一个值

rpop key 从右边弹出一个值

若值全部弹出,没有了,那么键也就没有了,再次弹出会返回nil(跟操作不存在的key一样,所以value没有是,key也就不存在了)

rpoplpush list1 list2 从list1末尾弹出一个值,插入到list2首位,并返回此值。

fErnoD.md.jpg

可以用来做任务消费队列及记录消费情况。比如list1是待消费任务队列,采用lpush的方式添加任务,消费时采用rpoplpush list1 list2的方式依照先进先出消费任务;然后将任务消费完成后移动到了list2中,list2用于记录已消费任务情况,越靠右端的消费的越早。

lrange list indexBegin indexEnd 获取对应索引范围内的值,前闭后闭

lrange list 0 -1 表示获取所有,-1代表右边第一个。这里不是假设,它确实代表右边第一个fErnoD.md.jpg

lindex list1 index 根据索引获取元素,从前往后数(从左到右),-1表示最后一个,当获取的index超出长度时,会返回nil。

llen list 获取列表长度,获取不存在的key会返回0而不是nil。这很契合“值在键在,值亡键亡”。所有没有值的键都一视同仁,而不是存在过的给0,没存在过的给nil。

linsert list before|after value newValue 在value前、在value后插入新值newValue。返回插入后list的长度。如果value不存在,那么返回-1,插入失败。

lrem list n value 从左边开始,删除n个value。返回实际删除的value个数。

lset list index value 将index位置的元素设置为value,成功返回OK,否则返回失败原因。-1表示倒数第一个元素,-2表示倒数第二个元素,当正数或倒数超出长度时,设置失败,返回(error) ERR index out of rangefErnoD.md.jpg

SET

set与list类似,都是一个列表,但是set可以自动排重,就是说若你需要储存一个列表数据,但是不希望出现重复数据时,set是一个较好的选择。且set提供了一个判断成员是否在set接口中的重要接口,这是list没有的。

Set是一个无序集合,和java的HashSet类似,底层是value为nul的hash表,所以增加,删除,查找元素的时间复杂度都是O(1)。(这意味着数据量增加时,查找数据的时间基本不变)

数据结构是dict字典,字典是用哈希表实现的。

sadd set value1 value2 将一个或多个元素储存到set中,重复或已存在的value将被忽略。返回本次命令实际储存的元素个数。

smembers set 查询该set集合的所有值。(无序)

sismembers set value 判断value是否存在于set中,存在返回1,不存在返回0。若集合set不存在,则也返回0。和list的“值在键在,值亡键亡”一样。

scard set 返回集合set中元素的个数。空集合或不存在的集合会返回0。

srem set value1 value2 删除集合中的一个或多个value元素,返回实际删除的元素个数。不存在的集合会返回0。

spop set 随机从集合set中弹出一个值并返回。(弹出=删除)

srandmember set n 随机从该集合set中返回n个值。(不会删除)

smove set1 set2 value 将value从set1中移动到set2中,移动成功返回1,不成功返回0;不能一次移动多个,否则报错(error) ERR wrong number of arguments for ‘smove’ command。移动之后元素就从set1中删除,在set2中新增;set2不存在则会创建,set1不存在则返回0。总之符合“值在键在,值亡键亡”。

sinter set1 set2 返回两个集合的交集元素。没有交集返回(empty array)

sunion set1 set2 返回两个集合的并集元素。

sdiff set1 set2 返回两个集合的差集元素。(set1中set2没有的元素,主语是set1)

Hash

hash是一个键值对集合,String类型的field-value映射表,类似于Java中的Map。hash适合储存对象。

数据结构:Hash类型对应的数据结构是两种:ziplist(压缩列表)、hashtable(哈希表)。当field-value长度较短且个数较少时使用前者,否则使用后者。

hset key field value field value 将一对或多对field value映射储存到key中,当存在重复的field时,靠后的value会覆盖靠前的。返回实际储存下去的field的个数。(参考Java中HashMap的储存情况:https://hanhanhanxu.github.io/2019/06/10/Hash/#more 1.3小节)

fErnoD.md.jpg

再此单独使用hset储存时,若field存在,虽然value储存到对应的key的field上了,但是hset命令仍会返回0。因为hset返回的是实际储存下去的field的个数

hget key field 从key中取出field的值。只能取一个,不存在的key,不存在的field,都会返回nil。

hgetall key 返回key中的key和value,返回的元素单数索引位置是key,索引+1,是对应的value。fErnoD.md.jpg

hexists key field 查看key中是否存在field,存在返回1,不存在(key不存在,key的field不存在)返回0。

hkeys key 返回该key中所有的field,不存在的key会返回(empty array)。

hvals key 返回该key中所有value,不存在的key同上。

hincrby key field n 给key中field对应的值加n。若field对应的value是存在的非数字字符串,则报错(error) ERR hash value is not an integer。若key或key中的field不存在,则自动创建并加上n。返回field对应value加n之后的结果。

hsetnx key field value 当且仅当key中field不存在时,设置进去field-value。key不存在或者key中field不存在都行。成功返回1,失败返回0。不能设置多个否则报错(error) ERR wrong number of arguments for ‘hsetnx’ command。

Zset

zset是有序集合(SortedSet),是一个没有重复元素的字符串集合。与set类似,不同的是它给每个元素都关联了一个评分(score),这个评分被用来按照从低到高给元素们排序。元素是唯一的,评分可以重复。

因为元素按照评分从低到高排序,所以也可以很快的根据评分来获取一个范围内的元素。访问中间元素也很快,所以可以把zset当成一个没有重复元素的列表。

zset底层使用了两个数据结构:1、hash,使用hash关联元素和其分值score(权重),保证元素的唯一,又可以通过元素找到对应score。2、跳跃表,用于给元素value排序,根据score范围获取元素列表。

zadd key score value score value 添加一个或多个元素及其评分。重复的元素会被覆盖,靠后添加的覆盖靠前的(不管评分大小)。返回实际添加元素的个数。

zrange key indexBegin indexEnd [withscores] 返回指定下标范围内的元素(元素按照评分从低到高排序),前闭后闭,-1代表最后一个,-2代表倒数第二个。带withscores会将评分也返回。fErnoD.md.jpg

zrevrange key indexBegin indexEnd [withsocres] 同上,返回元素按照评分从高到低排序时,指定下标范围内的元素。

zrangebyscore key min max [withscores] 返回分数大于等于min,小于等于max的元素,带withscores会将评分也返回。所有返回的元素按照score递增(从小min到大max)排序。fErnoD.md.jpg

zrevrangebyscore key max min [withscores] 同上,返回分数小于等于max大于等于min的元素,返回元素从大max到小min排序。fErnoD.md.jpg

zincrby key n value 给元素value的分值加n。若没有此元素或没有此zset,则自动新增一个,并加n。返回加n后的分值。

zrem key value1 value2 删除该zset中一个或多个value。返回实际删除成功的元素个数。若没有此zset或没有此value,则返回0。

zcount key min max 返回该集合下min,max分数区间的元素个数,前闭后闭。若没有此集合,返回0。

zcard key 返回该zset集合中元素的个数,不存在的key会返回0。

zrank key value 返回元素value在该集合中的排名,从0开始。

案例:使用zset实现阅读排行榜。

fErnoD.md.jpg

127.0.0.1:6379> del topn
(integer) 1
127.0.0.1:6379> zadd topn 0 a 0 b 0 c
(integer) 3
127.0.0.1:6379> zadd topn 0 d
(integer) 1
127.0.0.1:6379> zincrby topn 100 a
"100"
127.0.0.1:6379> zincrby topn 100 b
"100"
127.0.0.1:6379> zincrby topn 100 c
"100"
127.0.0.1:6379> zincrby topn 100 d
"100"
127.0.0.1:6379> zincrby topn 200 c
"300"
127.0.0.1:6379> zincrby topn 50 a
"150"
127.0.0.1:6379> zrevrange topn 0 9 withscores
1) "c"
2) "300"
3) "a"
4) "150"
5) "d"
6) "100"
7) "b"
8) "100"

4、配置文件

查看:less /myredis/redis.conf (less -N /myredis/redis 带行号查看)

按g 到文档头部,按G到文档尾部

j 下一行 k 上一行

f 向下翻页 b 向上翻页

/keyword 向下查找 ?keyword 向上查找

n 向下找下一个匹配文本 N 向上找上一个匹配文本

F 实时滚动 Ctrl + C 退出实时滚动 (当查看的文档是日志的话可以用这个)

q 退出less查看模式

redis配置文件中,大小写不敏感。例如daemonize YES,这里写成yes,YES都没事。

redis中的度量单位只支持bytes(字节),不支持bit(位,1字节=8位)。

fErnoD.md.jpg

可以使用include包含其他配置文件

fErnoD.md.jpg

网络

fErnoD.md.jpg

fErnoD.md.jpg

  • bind:默认bind=127.0.0.1 -::1,只接受本机访问请求,后面的-::1代表ipv6;如果不写bind,那么可接受任何ip地址访问。

  • protected-mode:保护模式。如果protected-mode为yes,那么在没有设置bind ip且没有密码时,redis只允许接收本机访问请求。如果为no,则运行外部网络直接访问。(此值默认是yes)

  • port:端口,默认6379,

  • tcp-backlog:连接队列的容量。设置tcp的backlog队列总量=未完成三次握手队列+已完成三次握手队列。

    在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。

    注意Linux内核会将这个值减小到/proc/sys/net/core/somaxconn的值(128),所以需要确认增大/proc/sys/net/core/somaxconn和/proc/sys/net/ipv4/tcp_max_syn_backlog(128)两个值来达到想要的效果

  • timeout:客户端空闲多少秒会关闭,0表示关闭该功能。默认0。

  • tcp-keepalive 对访问客户端的心跳检测,每多少秒检测一次。0表示不会进行检测。

    redis官方写的注释是:他有两个重要作用:1、检测死掉的客户端;2、将网络聚焦在那些活着的客户端上。这个值是发送ack的时间段,就是隔多少秒发送一次ack包,ack包用于tcp连接检测。

    好像也没有说如果检测到死掉的客户端就关闭啥的。看别人建议是设置为60秒,不太理解为啥。

通用

fErnoD.md.jpg

fErnoD.md.jpg

  • daemonize:守护进程,yes开启,no关闭。建议开启。

  • pidfile:存放pid文件的位置。每个实例会产生一个不同的Pid文件。(实例:一个运行中的redis服务。)

  • loglevel:日志级别。Redis总共支持四个级别:debug、verbose、notice(生产)、warning(生产),默认为notice

  • logfile:日志文件名称

  • databases:库的数量,默认16.

安全

fErnoD.md.jpg

  • requirepass:永久访问密码。(客户端执行config set requirepass password设置的密码是临时的,redis服务关掉后密码就没了。)
限制
  • maxclients:redis服务端同时可以与多少个客户端进行连接。默认10000(一万)。超出后对于发出连接的请求会拒绝并返回 max number of clients reached。

    fErnoD.md.jpg

  • maxmemory:redis服务端可以使用的内存量,建议设置,否则可能大量使用服务器内存,导致服务器宕机。到达上限后,redis会试图移除内部数据,移除规则可以通过maxmemory-policy设置。

    如果达到内存上限后,且根据规则无法再移除数据,则对于客户端那些需要申请内存才能完成的命令(set lpush等),会返回错误信息。对于无需申请内存就能完成的命令(get等),仍会正常响应。

  • maxmemory-policy:移除策略。

    • volatile-lru:对设置了过期时间的键,使用LRU算法移除key;( Least Recently Used 最近最少使用)

    • allkeys-lru:在所有集合key中,使用LRU算法移除key;

    • volatile-random:对设置了过期时间的键,在过期集合中移除随机的key;

    • allkeys-random:在所有集合key中,移除随机的key;

    • volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key;

    • noeviction:不进行移除。针对写操作,只是返回错误信息;(默认)

  • maxmemory-samples:样本数量。 LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小,redis默认会检查这么多个key并选择其中LRU的那个。一般设置3到7的数字,数值越小样本越不准确,但性能消耗越小。

fErnoD.md.jpg

5、发布订阅

发布订阅是一种消息通信模式:发送者(pub)发送消息,所有订阅者(sub)接收消息。详细来说是发布者将消息发布到某个频道(channel)里,订阅这个频道的订阅者就会收到消息。

Redis客户端可以订阅任意数量的频道。

可以直接使用命令进行对频道订阅,和将消息发送到频道里。

订阅频道:subscribe channel1 channel2

可以一次性订阅一个或多个频道

向频道发送消息:publish channel1 hello

一次只能向一个频道发送消息

案例:

操作

一个客户端订阅频道channel1、channle2:

fErnoD.md.jpg

另一个客户端订阅频道channel1:

fErnoD.md.jpg

最后一个客户端向channel1中发送一条消息hello,向channel2中发送一条消息word:(返回值是接收到消息的订阅者数量)

fErnoD.md.jpg

结果

第一个客户端收到两条消息:

fErnoD.md.jpg

第二个客户端收到一条消息:

fErnoD.md.jpg

6、新数据类型

  • Bitmaps:对“位”进行操作

  • HyperLogLog:基数(不重复的数据集)统计

  • Geospatial:经纬度支持

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值