Redis
Redis
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
数据结构
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet;HyperLogLog、Geo、Pub/Sub;Redis Module,像BloomFilter,RedisSearch,Redis-ML。
Redis登录授权
本地写demo启动的redis一般都是没有密码的,我们正式环境应该把redis设置密码。打开redis.conf文件,找到requirepass部分,改成自己的密码,设置后记得重启,在配置了密码的情况下,没有进行授权,那么对Redis发送的命令,将返回"(error) NOAUTH Authentication required."。
配置文件redis.conf
redis.conf中一些常用配置:
配置 | 作用 | 默认 |
bind |
当配置了bind之后:
|
127.0.0.1 |
protected-mode |
protected-mode是Redis3.2之后的新特性,用于加强Redis的安全管理,当满足以下两种情况时,protected-mode起作用:
当满足以上两种情况且protected-mode=yes的时候,访问Redis将报错,即密码未设置的情况下,无密码访问Redis只能通过安装Redis的本机进行访问 |
yes |
port | Redis访问端口,由于Redis是单线程模型,因此单机开多个Redis进程的时候会修改端口,不然一般使用大家比较熟悉的6379端口就可以了 | 6379 |
tcp-backlog | 半连接队列的大小,对半连接队列不熟的可以看我以前的文章TCP:三次握手、四次握手、backlog及其他 | 511 |
timeout | 指定在一个client空闲多少秒之后就关闭它,0表示不管 | 0 |
tcp-keepalive |
设置tcp协议的keepalive,从Redis的注释来看,这个参数有两个作用:
|
300 |
daemonize | 这个前面说过了,指定Redis是否以守护进程的方式启动 | no |
supervised | 这个参数表示可以通过upstart和systemd管理Redis守护进程,这个具体和操作系统相关,资料也不是很多,就暂时不管了 | no |
pidfile | 当Redis以守护进程的方式运行的时候,Redis默认会把pid写到pidfile指定的文件中 | /var/run/redis_6379.pid |
loglevel |
指定Redis的日志级别,Redis本身的日志级别有notice、verbose、notice、warning四种,按照文档的说法,这四种日志级别的区别是:
|
notice |
logfile | 配置log文件地址,默认打印在命令行终端的窗口上 | "" |
databases | 设置Redis数据库的数量,默认使用0号DB | 16 |
save | 把Redis数据保存到磁盘上,这个是在RDB的时候用的,介绍RDB的时候专门说这个 |
save 900 1 save 300 10 save 60 10000 |
stop-writes-on-bgsave-error |
当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。 这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。 如果Redis重启了,那么又可以重新开始接收数据了 |
yes |
rdbcompression | 是否在RBD的时候使用LZF压缩字符串,如果希望省点CPU,那就设为no,不过no的话数据集可能就比较大 | yes |
rdbchecksum | 是否校验RDB文件,在RDB文件中有一个checksum专门用于校验 | yes |
dbfilename | dump的文件位置 | dump.rdb |
dir | Redis工作目录 | ./ |
slaveof | 主从复制,使用slaveof让一个节点称为某个节点的副本,这个只需要在副本上配置 | 关闭 |
masterauth | 如果主机使用了requirepass配置进行密码保护,使用这个配置告诉副本连接的时候需要鉴权 | 关闭 |
slave-serve-stale-data |
当一个Slave与Master失去联系或者复制正在进行中,Slave可能会有两种表现:
|
yes |
slave-read-only | 配置Redis的Slave实例是否接受写操作,即Slave是否为只读Redis | yes |
slave-priority | 从站优先级是可以从redis的INFO命令输出中查到的一个整数。当主站不能正常工作时,redis sentinel使用它来选择一个从站并将它提升为主站。 低优先级的从站被认为更适合于提升,因此如果有三个从站优先级分别是10, 100, 25,sentinel会选择优先级为10的从站,因为它的优先级最低。 然而优先级值为0的从站不能执行主站的角色,因此优先级为0的从站永远不会被redis sentinel提升。 |
100 |
requirepass | 设置客户端认证密码 | 关闭 |
rename-command |
命令重命名,对于一些危险命令例如:
作为服务端redis-server,常常需要禁用以上命令来使得服务器更加安全,禁用的具体做法是是:
也可以保留命令但是不能轻易使用,重命名这个命令即可:
这样,重启服务器后则需要使用新命令来执行操作,否则服务器会报错unknown command |
关闭 |
maxclients | 设置同时连接的最大客户端数量,一旦达到了限制,Redis会关闭所有的新连接并发送一个"max number of clients reached"的错误 | 关闭,默认10000 |
maxmemory | 不要使用超过指定数量的内存,一旦达到了,Redis会尝试使用驱逐策略来移除键 | 关闭 |
maxmemory-policy |
当达到了maxmemory之后Redis如何移除数据,有以下的一些策略:
注意,当写操作且Redis发现没有合适的数据可以移除的时候,将会报错 |
关闭,noeviction |
appendonly | 是否开启AOF,关于AOF后面再说 | no |
appendfilename | AOF文件名称 | appendonly.aof |
appendfsync |
操作系统实际写数据到磁盘的频率,有以下几个选项:
当不确定是使用哪种的时候,官方推荐使用everysec,它是速度与数据安全之间的一种折衷方案 |
everysec |
no-appendfsync-on-rewrite |
aof持久化机制有一个致命的问题,随着时间推移,aof文件会膨胀,当server重启时严重影响数据库还原时间,因此系统需要定期重写aof文件。 重写aof的机制为bgrewriteaof(另外一种被废弃了,就不说了),即在一个子进程中重写从而不阻塞主进程对其他命令的处理,但是这依然有个问题。 bgrewriteaof和主进程写aof,都会操作磁盘,而bgrewriteaof往往涉及大量磁盘操作,这样就会让主进程写aof文件阻塞。 针对上述问题,可以使用此时可以使用no-appendfsync-on-rewrite参数做一个选择:
|
no |
auto-aof-rewrite-percentage | 本次aof文件超过上次aof文件该值的百分比时,才会触发rewrite | 100 |
auto-aof-rewrite-min-size | aof文件最小值,只有到达这个值才会触发rewrite,即rewrite由auto-aof-rewrite-percentage+auto-aof-rewrite-min-size共同保证 | 64mb |
aof-load-truncated |
redis在以aof方式恢复数据时,对最后一条可能出问题的指令的处理方式:
|
yes |
slowlog-log-slower-than | Redis慢查询的最低条件,单位微妙,即查询时间>这个值的会被记录 | 10000 |
slowlog-max-len | Redis存储的慢查询最大条数,超过该值之后会将最早的slowlog剔除 | 128 |
lua-time-limit | 一个lua脚本执行的最大时间,单位为ms | 5000 |
cluster-enabled | 正常来说Redis实例是无法称为集群的一部分的,只有以集群方式启动的节点才可以。为了让Redis以集群方式启动,就需要此参数。 | 关闭 |
cluster-config-file | 每个集群节点应该有自己的配置文件,这个文件是不应该手动修改的,它只能被Redis节点创建且更新,每个Redis集群节点需要不同的集群配置文件 | 关闭,nodes-6379.conf |
cluster-node-timeout | 集群中一个节点向其他节点发送ping命令时,必须收到回执的毫秒数 | 关闭,15000 |
cluster-slave-validity-factor |
如果该项设置为0,不管Slave节点和Master节点间失联多久都会一直尝试failover。 比如timeout为5,该值为10,那么Master与Slave之间失联50秒,Slave不会去failover它的Master |
关闭,10 |
cluster-migration-barrier |
当一个Master拥有多少个好的Slave时就要割让一个Slave出来。 例如设置为2,表示当一个Master拥有2个可用的Slave时,它的一个Slave会尝试迁移 |
关闭,1 |
cluster-require-full-coverage |
有节点宕机导致16384个Slot全部被覆盖,整个集群是否停止服务,这个值一定要改为no |
关闭,yes |
具体详情这篇博文:https://www.cnblogs.com/xrq730/p/8890896.html
基本操作命令
DEL 删除Key, del key1 key2
EXISTS 检查key是否存在, EXISTS key
EXPIRE 设置或者更新到期时间,到期后自动清除,单位秒 设置为-1表示永不过期。 EXPIRE key
PERSIST 移除过期时间,key永久保存。其实就是过期时间设置为-1,永不过期
PTTL 以毫秒为单位返回key剩余的过期时间。
TTL 以秒为单位,返回给定key的剩余生存时间。
EXPIREAT 设置key的过期时间,不过设置的是时间戳。
PEXPIRE 设置key的过期时间,不过是毫秒单位。
PEXPIREAT 设置key的过期时间,不过是时间戳,以毫秒统计。
KEYS pattern 查找匹配给定模式pattern的所有key。
KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
特殊符号用 \ 隔开
MOVE key db 把指定的key移动到数据库db中。(默认的redis有16个数据库)
SELECT index 切换数据库(redis默认16个数据库 编号从0开始)
RANDOMKEY 随机获取一个key
RENAME key newkey 修改key名字。如果newkey已经存在,则删除newkey。
RENAMENX key newkey 仅当newkey不存在时,将key改名为newkey。
TYPE key 返回key的类型
具体可参考这篇博文:https://www.cnblogs.com/wudequn/p/8080078.html
集群
Redis Sentinal(哨兵模式)着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster(redis3.0版本以后支持)着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
两者主要区别是哨兵模式是主从结构,Cluster可选择主从或从从结构。还有其他集群模式等。
持久化
RDB(默认开启)指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
AOF(默认关闭)指以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
RDB持久化配置
Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
AOF持久化配置
在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不同步。高效但是数据不会被持久化。
同步机制
可以使用主从同步,从从同步。
第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。
加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
数据淘汰策略(6种回收策略)
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
面试问题
redis的并发竞争问题如何解决?
Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题。
这些问题均是由于客户端连接混乱造成。对此有2种解决方法:
1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
2.服务器角度,利用setnx实现锁。
对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;
第二种需要用到Redis的setnx命令,但是需要注意一些问题。拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。如果在setnx之后执行expire之前进程意外crash或者要重启维护了,
set指令有非常复杂的参数,可以同时把setnx和expire合成一条指令来用。
假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
使用keys指令可以扫出指定模式的key列表。如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。
这个时候可以使用scan指,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。
如果有大量的key需要设置同一时间过期,一般需要注意什么?
如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。
Redis如何做持久化的?
bgsave做镜像全量持久化,aof做增量持久化。bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。在redis实例重启时,优先使用aof来恢复内存的状态,如果没有aof日志,就会使用rdb文件来恢复。
aof文件过大恢复时间过长怎么办?Redis会定期做aof重写,压缩aof文件日志大小。Redis4.0之后有了混合持久化的功能,将bgsave的全量和aof的增量做了融合处理,这样既保证了恢复的效率又兼顾了数据的安全性。
如果突然机器掉电会怎样?取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,最多就会丢失1s的数据。
bgsave的原理是什么?fork和cow。fork是指redis通过创建子进程来进行bgsave操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
Pipeline有什么好处,为什么要用pipeline?
可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。
redis事物的了解CAS(check-and-set 操作实现乐观锁 )?
在Redis中,MULTI/EXEC/DISCARD/WATCH这四个命令是我们实现事务的基石。
Redis中事务的实现特征:
1). 在事务中的所有命令都将会被串行化的顺序执行,事务执行期间,Redis不会再为其它客户端的请求提供任何服务,从而保证了事物中的所有命令被原子的执行。
2). 和关系型数据库中的事务相比,在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。
3). 我们可以通过MULTI命令开启一个事务,有关系型数据库开发经验的人可以将其理解为"BEGIN TRANSACTION"语句。
在该语句之后执行的命令都将被视为事务之内的操作,最后我们可以通过执行EXEC/DISCARD命令来提交/回滚该事务内的所有操作。这两个Redis命令可被视为等同于关系型数据库中的COMMIT/ROLLBACK语句。
4). 在事务开启之前,如果客户端与服务器之间出现通讯故障并导致网络断开,其后所有待执行的语句都将不会被服务器执行。然而如果网络中断事件是发生在客户端执行EXEC命令之后,那么该事务中的所有命令都会被服务器执行。
5). 当使用Append-Only模式时,Redis会通过调用系统函数write将该事务内的所有写操作在本次调用中全部写入磁盘。如果在写入的过程中出现系统崩溃,如宕机,那么此时也许只有部分数据被写入到磁盘,而另外一部分数据却已经丢失。
Redis服务器会在重新启动时执行一系列必要的一致性检测,一旦发现类似问题,就会立即退出并给出相应的错误提示。
此时,我们就要充分利用Redis工具包中提供的redis-check-aof工具,该工具可以帮助我们定位到数据不一致的错误,并将已经写入的部分 数据进行回滚。修复之后我们就可以再次重新启动Redis服务器了。
WATCH命令和基于CAS的乐观锁:
在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能。假设我们通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,
同时返回Null multi-bulk应答以通知调用者事务执行失败。例如,我们再次假设Redis中并未提供incr命令来完成键值的原子性递增,如果要实现该功能,我们只能自行编写相应的代码。其伪码如下:
val = GET mykey
val = val + 1
SET mykey $val
以上代码只有在单连接的情况下才可以保证执行结果是正确的,因为如果在同一时刻有多个客户端在同时执行该段代码,那么就会出现多线程程序中经常出现的一种错误场景--竞态争用(race condition)。
比如,客户端A和B都在同一时刻读取了mykey的原有值,假设该值为10,此后两个客户端又均将该值加一后set回Redis服务器,这样就会导致mykey的结果为11,而不是我们认为的12。为了解决类似的问题,我们需要借助WATCH命令的帮助,代码:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
和此前代码不同的是,新代码在获取mykey的值之前先通过WATCH命令监控了该键,此后又将set命令包围在事务中,这样就可以有效的保证每个连接在执行EXEC之前,如果当前连接获取的mykey的值被其它连接的客户端修改,
那么当前连接的EXEC命令将执行失败。这样调用者在判断返回值后就可以获悉val是否被重新设置成功。
redis的缓存失效策略和主键失效机制
作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略.在Redis当中,有生存期的key被称为volatile。在创建缓存时,要为给定的key设置生存期,当key过期的时候(生存期为0),它可能会被删除。
1、影响生存时间的一些操作生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆盖原来的数据,也就是说,修改key对应的value和使用另外相同的key和value来覆盖以后,当前数据的生存时间不同。比如说,对一个 key 执行INCR命令,对一个列表进行LPUSH命令,或者对一个哈希表执行HSET命令,这类操作都不会修改 key 本身的生存时间。另一方面,如果使用RENAME对一个 key 进行改名,那么改名后的 key的生存时间和改名前一样。RENAME命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。使用PERSIST命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个persistent key 。
2、如何更新生存时间可以对一个已经带有生存时间的 key 执行EXPIRE命令,新指定的生存时间会取代旧的生存时间。过期时间的精度已经被控制在1ms之内,主键失效的时间复杂度是O(1),EXPIRE和TTL命令搭配使用,TTL可以查看key的当前生存时间设置成功返回 1;当 key 不存在或者不能为 key 设置生存时间时,返回 0 。最大缓存配置在 redis 中,允许用户设置最大使用内存大小server.maxmemory默认为0,没有指定最大缓存,如果有新的数据添加,超过最大内存,则会使redis崩溃,所以一定要设置。redis 内存数据集大小上升到一定大小的时候,就会实行数据淘汰策略。
redis 提供 6种数据淘汰策略:
. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
. no-enviction(驱逐):禁止驱逐数据
注意这里的6种机制,volatile和allkeys规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据,后面的lru、ttl以及random是三种不同的淘汰策略,再加上一种no-enviction永不回收的策略。
使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random
三种数据淘汰策略:
ttl和random比较容易理解,实现也会比较简单。主要是Lru最近最少使用淘汰策略,设计上会对key 按失效时间排序,然后取最先失效的key进行淘汰
redis 最适合的场景
Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,似乎Redis更像一个加强版的Memcached,比较与Memcached的区别,会得到以下观点:
1 、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2 、Redis支持数据的备份,即master-slave模式的数据备份。
3 、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
(1)会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,
他们还会这样吗?幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
(2)全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。
(3)队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis
queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
(4)排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。
所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:当然,这是假定你是根据你用户的分数做递增的排序。
如果你想返回用户及用户的分数,你需要这样执行:ZRANGE user_scores 0 10 WITHSCORES 。Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。
(5)发布/订阅
是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统。
具体代码参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!