Redis学习:BigKey、缓存双写一致性更新策略和案例

Redis学习:BigKey、缓存双写一致性更新策略和案例

文章目录

  • Redis学习:BigKey、缓存双写一致性更新策略和案例
    • 1. BigKey
    • 2. 缓存双写一致性更新策略
    • 3. 缓存双写一致性案例

1. BigKey

  1. 面试题
    1. MoreKey不可以使用keys * ,要使用SCAN基于游标来查询所有的key
    2. 通过在redis.conf配置文件中修改SECURITY配置项,将这些指令重命名或者禁用
    3. MEMORY USAGE key查询指定key所占用的字节数,也可以使用redis-cli –bigkeys查看每个类型占用字节最多的key,以及key的个数和平均大小
    4. BigKey是指某个key的value太大string类型超过10k,其他类型hash\list\set\zset超过5000个元素就是bigkeystring类型可以直接使用del阻塞删除,其他类型不可以使用del,会造成阻塞,而是用渐进式删除,一部分一部分进行删除,通过HSCAN\SSCAN\ZSCAN来获取对应类型key中value中的数据,然后一部分一部分进行删除
    5. BigKey调优,因为redis有del阻塞删除和unlink非阻塞删除,而默认使用del阻塞删除,故可以在redis.conf配置文件中修改LAZYFREE配置项实现非阻塞删除,以进行优化
    6. MoreKey时,不可以直接使用Keys * 进行遍历,会严重阻塞,要使用SCAN 游标 模式 个数 命令基于游标进行遍历所有的key,每次会返回下一次遍历开始的游标以及近似个数的匹配的key
    7. MoreKey是指redis中key的个数过多而BigKey是指某个Key的value过大
    8. SCAN是遍历KeyHSCAN\SSCAN\ZSCAN是遍历指定类型key中的value
  2. MoreKey案例(简历加分)
    1. 向Redis中插入大量数据
      1. 先使用linux操作创建一个文件,里面存放了一百万条set指令,使用管道指令将所有的指令在Redis中运行
      2. 使用DBSIZE可以查看Redis数据库中的key的个数
    2. 禁用keys * 等指令
      1. 数据量很大时,一定要避免使用keys * ,可以直接在配置文件中禁止该指令
      2. 当数据量很大时,不要使用keys * 和flushdb因为Redis只有主线程串行执行命令,且keys * 是遍历实现的,故会非常耗费时间,造成Redis主线程卡顿,则此时后面的所有请求的命令均会卡顿
      3. 通过在redis.conf配置文件中设置SECURITY配置项禁止这些命令,或者重命名,更改配置文件后一定要先重启服务端
    3. 使用SCAN遍历Morekey
      1. SCAN是从游标开始遍历指定个数的匹配的key而HSCAN\SSCAN\ZSCAN是遍历指定类型key中value的元素,是删除BigKey时遍历当前key中的元素进行删除
      2. 当redis数据库中key很多时,要禁止使用keys * 、FLUSHDB等危险指令,可以在redis.conf的SECURITY配置项中进行配置,此时如果要遍历数据库中的key,要使用SCAN指令基于游标进行遍历,SCAN指令是遍历所有的key,可以指定匹配的模式,以及遍历的大概数目,且返回下一次遍历的游标,当游标为0时说明遍历结束
      3. SCAN 游标 匹配模式 个数:SCAN是基于游标的迭代,每次要指定一个游标,返回下一次开始的游标以及近似数量的key,当游标返回0时说明匹配的key遍历结束
      4. 使用scan命令查找指定的key(不使用keys * )使用SCAN遍历匹配的key,使用HSCAN/SSCAN/ZSCAN遍历指定 key(bigkey) 中的元素
      5. Scan命令用于迭代数据库中的数据库键,是基于游标的迭代器,当前遍历要基于上一次遍历的游标
      6. SCAN命令基于游标来遍历数据库中的所有key,游标从0开始,每次返回下一次遍历的游标和当前遍历的key(不保证数量),不是顺序遍历,而是高位进位加法遍历
      7. SCAN命令的意思就是对所有满足条件的key进行非顺序遍历,而是基于游标遍历,每次返回模糊数量的key,以及下一次遍历游标,直到所有的遍历结束返回游标0
      8. SCAN遍历所有的key,不是顺序遍历,而是基于游标进行遍历,高位加法遍历
  3. BigKey案例(key的value非常大)
    1. 多大的key算big
      1. MoreKey是指key非常多,BigKey是指某个key的value非常大
      2. BigKey是指value非常大,不是key大
      3. 非字符串的bigkey,不要使用del删除,而且要注意过期时间,当过期后会自动使用del进行删除,字符串的bigKey使用del进行阻塞删除,而非string的bigKey要使用渐进式删除,一部分一部分删除,或者使用lazyfree,要在配置文件中进行配置,默认是关闭的
      4. string类型的key的value最大是512M,但超过10K就是bigkey
      5. list\hash\set\zset类型的key,最多可以2^32 - 1 个元素,但数量超过5000就是bigkey
    2. 哪些危害:内存不均、超时删除、网络阻塞
    3. 如何产生:社交粉丝、报表积累
    4. 如何发现
      1. 使用redis-cli --bigkeys可以返回每个数据类型的最大的bigkey,以及该类型key的数目和平均大小,此时可以对最大的bigkey进行删除,string类型可以直接阻塞del删除,但非string不要使用del,而是渐进式删除,且对于key,可以通过MEMORY USAGE key,查看某个key所占用的内存字节数
      2. redis-cli –bigkeys
        1. 给出每个数据结构最大的bigkey,同时给出每个数据类型的个数 + 平均大小
        2. 只给出TOP1的bigkey无法查询所有的bigkey,要使用SCAN查询所有的key,并使用MEMORY USAGE key查看某个key占用内存
        3. –bigkeys底层使用SCAN进行扫描,可以使用 -i time 添加每100个SCAN的时间间隔
      3. MEMORY USAGE key
        1. 给出指定的key所占用的字节数
    5. 如何删除bigkey
      1. 非string类型先使用HSCAN/SSCAN/ZSCAN遍历指定key中的部分value,然后删除继续遍历,一部分一部分渐进式删除
      2. 使用HSCAN\ZSCAN\SSCAN遍历的是指定类型key中value的元素,然后再渐进式删除,遍历指定key中的value,再使用渐进式删除一部分一部分删除,字符串类型直接阻塞del删除,非string使用渐进式删除,且所有的key过期后均会默认使用del阻塞删除,要通过配置lazyfree配置项来开启非阻塞删除,key到期后默认使用del删除
      3. 非字符串的bigkey,不要使用del(del会直接全部删除),要使用渐进式删除,一部分一部分的删除,不要直接全部删除,且key过期后会自动默认使用del进行删除造成阻塞
      4. string类型使用del进行删除,或者使用unlink异步删除
      5. 非string类型不要用del直接删除,因为太大时会造成网络阻塞,要使用渐进式删除,一部分一部分删除
      6. hash类型使用渐进式删除,一部分一部分删除,通过HSCAN key查看当前hash类型的bigkey中的部分value,然后删除,继续遍历,一部分一部分渐进式删除,不要一下使用del全部删除
      7. list类型使用 LTRIM start end 进行修建,不在区间内的将被删除,list类型使用LTRIM修建,不在区间内的全部删除,故每次可以只修建前面指定个数的元素,直到末尾
      8. set类型使用SREM
  4. BigKey生产调优 LazyFree配置项
    1. key过期默认是使用del阻塞删除的,如果对于string可以,但对于非string不要使用del进行删除,此时就应该修改配置文件,对lazyfree配置项进行配置,已开启非阻塞删除
    2. 默认是使用del阻塞删除的,故可以通过在配置文件中修改FLAZYFREE配置使其非阻塞删除进行优化
    3. redis提供两种删除方法:del(阻塞)、unlink(非阻塞)默认是使用del阻塞删除,在配置文件中修改lazyfree配置项

2. 缓存双写一致性更新策略

  1. 面试题:写策略
    1. 缓存和数据库一致性问题:更新数据时要保证MySQL数据库的准确性,故先更新MySQL再删除缓存,此时会出现脏读,但可以保证最终一致性;读取数据时,当缓存不存在则要从MySQL读取,如果高并发必须加锁,否则会全打到MySQL上,而且加锁后要再检查是否已经写入缓存,此时就可以一次MySQL操作实现缓存回写,即双检加锁;如果先删除缓存再更新数据库,则为了保证最后的一致性,在MySQL更新前如果有读取缓存,则会从旧的MySQL中读出数据并写回缓存,此时MySQL更新后因为不会重新删除缓存,就会导致不一致,故要使用双删延迟,即先删除缓存,然后更新数据库,然后延迟一个读操作保证之间的读操作已经写回缓存最后再删除缓存,此时就算有读操作也是从更新后的数据库读取数据写入缓存
    2. 为了保证MySQL和redis缓存的一致性,可以使用canal中间件对MySQL的增量文件进行解析订阅和消费,其实时监控MySQL的binlog,可以在canal客户端连接canal服务端然后subscribe订阅指定数据库的库和表,此时就可以获得增量文件中未确认的数据,即变动的数据,然后对这些数据打印并进行相应的处理,以实现和Redis缓存的一致性
  2. 缓存双写一致性
    1. 一致性,如果redis中有数据则必须与数据库一致;如果redis无数据,则保证数据库中为最新值,且要准备写入redis
    2. 缓存可以分为只读缓存和读写缓存对于只读缓存不需要回写操作,对于读写缓存必须保证回写的一致性
    3. 对于读写缓存,当redis中无数据时,有两种回写策略:同步直写和异步缓写同步直写是将数据库数据直接写入redis缓存异步缓写是先不写入缓
    4. 如何实现:当读取redis无数据时,要使用双检加锁来防止MySQL击穿
      1. 双检加锁策略
        1. 检查两次缓存是否存在第一次不存在时加锁访问MySQL将数据写入缓存且在锁里再进行一次检查保证只有一次查询MySQL,防止击穿MySQL
        2. 当同时查询缓存时,如果存在则直接返回,否则对第一个查询数据上加锁,由一个线程去查询并写入缓存,且在锁里面再做一次查询,此时后边等待的进程进入锁后会直接返回,保证只进行一次MySQL查询
      2. 当并发量很大时,缓存不存在时可能全部去MySQL查找造成缓存击穿,且可能会redis数据覆盖,故必须使用双检加锁策略,读取redis数据时必须使用双检加锁,第一次检查缓存无数据时,加锁去从MySQL中读取数据,且在锁中再检查一次,不存在时再去读取MySQL,此时就可以保证只有一次访问MySQL;更新数据时,使用先更新数据库再删除缓存策略,或者双删延迟
      3. 当并发量很小时,可以如下写法,可以不加锁,但并发量很大时,必须加锁访问MySQL
  3. 数据库和缓存一致性的几种更新策略
    1. 以MySQL写入库的数据为准,要保证最终一致性
    2. 可以停机的情况
      1. 直接停机后保证数据的一致性
    3. 不可以停机更新策略
      没有完美的方案都不可避免的会出现脏读,但要保证最终数据的一致性
      只有缓存不存在时才会从MySQL中读取数据并回写,当更新MySQL后不会进行回写,更新MySQL数据库后不会回写进入缓存,但读取redis不存在时会双检加锁读取MySQL再写入redis,要保证以MySQL为准,故必须先更新MySQL
      1. 先更新数据库再更新缓存×
        1. 如果缓存更新失败会导致不一致,更新缓存时可能导致不一致
        2. 先更新数据库再删除缓存不会造成最终的数据不一致,但要是更新缓存则会造成数据不一致
        3. 且并发执行时,缓存更新结果可能不一致
      2. 先更新缓存再更新数据库×
        1. 要保证以MySQL为准,故必须先更新MySQL
        2. 不推荐,因为要以MySQL为准,故要保证MySQL数据库始终正确
        3. 且高并发下也会出现顺序错误,有快有慢使得更新顺序错误
      3. 先删除缓存再更新数据库
        1. 因为更新后不会修改redis,故可能会造成最终数据的不一致,故必须使用双删延迟
        2. 延时双删:就是更新前先删除缓存的值,然后更新,更新后再删除缓存的值第二次删除要延时一个读操作的时间保证读操作已经回写进入缓存后再进行删除,此时不可避免的会出现有一次读操作会读到脏数据,但可以保证最终数据一致性,但是一次读操作时间不好估计
        3. 如果不使用延时双删,则可能会导致缓存和数据库始终不一致,如还未 更新MySQL就读缓存将旧数据放入缓存中,此时MySQL更新完成,则此时的缓存和MySQL就不一致更新完MySQL后不会再更新缓存,故必须延时双删
        4. 当缓存中不存在时,就回去MySQL数据库中查找值
        5. 可能出现A更新MySQL还未完成时,B读缓存不存在然后读MySQL并回写缓存,此时A再更新MySQL就会出现不一致,可以使用延时双删来解决
        6. 通过回写来保证缓存的一致性,当缓存没有时会从数据库回写进入缓存
        7. 但如果删除缓存后正在更新MySQL但还未完成,此时访问数据就会读到MySQL中的旧数据,且还会把旧值写回缓存
      4. 先更新数据库再删除缓存
        1. 要保证MySQL为准,故必须先更新MySQL,然后删除缓存可以保证最终数据一致性
        2. 不可避免的会出现脏读,但要保证最终数据的一致性
        3. 此时会存在幻读,当MySQL还未更新时有线程读操作就会读到更新前的旧值
  4. 小总结
    1. 读取缓存使用双检加锁,更新数据时使用先更新数据库再删除缓存
    2. 缓存双写一致性,要保证最终数据一致性,当缓存数据不存在时使用双检加锁来从MySQL中回写入缓存中,读取缓存时要使用双检加锁,更新数据时要先更新数据库再删除缓存,此时读取读到不存在时使用双检加锁
    3. 更新数据时优先使用先更新数据库再删除缓存策略来保证缓存和数据库最终数据的一致性
    4. 如果使用先删除缓存再更新数据库,则要使用双删延迟,先删除缓存然后更新数据库,然后延迟一段时间后再删除缓存,此时延迟的时间不好估计,如果不使用双删延迟,则可能会导致最终不一致,因为更新完数据库后不会进行回写

3. 缓存双写一致性案例

  1. 复习与面试题
    1. 保证最终一致性,且以MySQL为准
    2. 更新时使用先更新数据库再删除缓存读取时使用双检加锁
    3. 如何将MySQL的改变同步反应到缓存中,使用canal中间件监听binlog日志去监控MySQL的改变,并在客户端实时写入Redis
  2. Canal:监听MySQL并通知Redis
    1. 是什么:基于MySQL数据库增量日志解析,提供增量数据订阅和消费
      1. 类似于Redis的AOF持久化,将MySQL的增量数据保存并发布给其他组件
      2. 基于MySQL数据库增量日志解析提供增量数据订阅和消费
    2. 工作原理
      1. MySQL主从复制原理,MySQL有一个binlog日志,记录增量
      2. Canal工作原理,基于MySQL增量日志解析,提供订阅和消费
    3. MySQL-canal-Redis双写一致性
      1. canal实时监控MySQL的更新,并同步给Redis,基于MySQL数据库增量日志解析,提供增量数据订阅和消费
      2. MySQL要开启binlog并配置canal账户
        1. 配置MySQL开启binlog二进制文件,并配置一个canal账户授予权限
        2. 开启MySQL的binlog写入功能,MySQL8默认开启
        3. 授权canal连接MySQL账号,默认MySQL中没有canal用户,此时要新建+授权
      3. Canal服务端
        1. 下载:在github上下载alibaba的canal开发版本
        2. 解压
        3. 配置
          1. 客户端会读取默认的配置文件,当设置了则进行覆盖
          2. 保证canal能够连接到MySQL的服务端,故要配置MySQL的IP和Port,并换成自己在MySQL上创建的canal用户
      4. Canal客户端
        使用Java编写canal客户端来监控MySQL数据库的变动并通知给Redis
        1. 建项目
        2. 改POM:要引入canal有关的依赖,去github的wiki操作文档
        3. 写YML
        4. 主启动
        5. 业务类
          1. RedisUtils
            1. 返回jedis连接的工具类,内部创建的jedis连接池,可以返回一个jedis连接
          2. RedisCanalClientExample
            1. 去github的官网上找example
            2. main中先创建canal连接,然后订阅指定库表的变动不要订阅全部库的全部表),然后获得MySQL中监听到的未确认的数据,如果为0说明没有数据改变,此时继续监听,如果不为0说明有数据变动,则打印printEntry获得的数据变动,然后对这些变动进行确认
            3. 在printEntry函数中,此时传入了数据变动的Entry,要对每个entry进行自定义的业务处理以及打印,for循环遍历所有的entry,然后判断每个变动的类型,根据类型调用相应的方法对Redis进行实现相应的操作,原始操作只是打印,如果要实现同步数据到Redis,要自己创建相应的函数来实现Redis数据的更新
          3. 通过canal客户端和服务端可以实现对MySQL数据库指定库表数据的实现监控,并得到变动的数据根据业务需求将变动数据更新到redis中,可以在canal客户端中编写相应的功能实现对Redis数据的一致性更新,相应操作根据业务需求自己编写
          4. 在main函数中获得canal连接后,要通过**connector.subscribe(“库.表(正则表达式)”)**订阅指定库表的变动,此时不要订阅所有的库表,否则会监控所有变动造成很大开销,也可以配置黑名单来指定不监控的库和表
          5. 当canal客户端某个配置未显式配置时,会自动读取配置文件中的配置,当配置了会覆盖配置文件中的配置,而默认是订阅所有的库和表
          6. try-with-resources释放资源,在try指令内的部分对象会自动关闭,不需要自己释放
      5. 小总结
        1. 通过使用canal中间件监控MySQL数据库的变动并实时回写进入Redis实现强一致性
        2. canal服务端会自动监听MySQL的数据变动,然后创建canal客户端来获得监听数据并回写到指定的Redis中

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Ps:天空替换

Ps菜单:编辑/天空替换 Edit/Sky Replacement Ps菜单:选择/天空 Select/Sky 天空替换 Sky Replacement命令能够自动分析前景与天空,利用 Adobe Sensei 技术也大大减轻了制作蒙版的负担,可以直观、智能、快速地实现天空替换。 到目…

【JavaEE初阶】网络编程TCP协议实现回显服务器以及如何处理多个客户端的响应

前言 🌟🌟本期讲解关于TCP/UDP协议的原理理解~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不多说…

MySQL 9从入门到性能优化-加密函数

【图书推荐】《MySQL 9从入门到性能优化(视频教学版)》-CSDN博客 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

探索空间计算与 VR 设备的未来:4K4DGen 高分辨率全景 4D 内容生成系统

在当今科技飞速发展的时代,空间计算和 VR 设备正逐渐成为人们体验沉浸式场景的重要工具。而今天,我们要为大家介绍一款具有创新性的技术 ——4K4DGen 高分辨率全景 4D 内容生成系统,它为 VR/AR 沉浸式体验带来了全新的可能性。 一、项目概述 4K4DGen 项目的核心目标是实现 …

Unity中实现伤害飘字或者提示飘字效果(DoTween实现版本)

!!!在实现以下效果之前,一定要往项目中导入DoTween插件。 一、搭建测试场景 1、在场景中新建一个带有Text组件的游戏物体A,并把这个游戏物体A中Text组件的Color属性中alpha值为0,让文字在场景中隐藏。 …

为什么说模拟电路的难点就在开通过程和关断过程?难在什么地方?

模拟电路中开通过程和关断过程之所以困难,主要有以下几个方面的原因: 1. 瞬态响应特性复杂 - 在开通和关断瞬间,电路中的电流和电压会发生快速变化,产生复杂的瞬态响应。这些瞬态响应可能包含过冲、下冲、振铃等现象,…

数据结构---二叉树(顺序结构),堆(上)

树 树的概念与结构 树是⼀种⾮线性的数据结构,它是由 n(n>=0) 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树,也就是说它是根朝上,⽽叶朝下的。 PS 有⼀个特殊的结点,称为根结点,根结点没有前驱结点。除根结点外,其余结点被分成…

CSS中常见的两列布局、三列布局、百分比和多行多列布局!

目录 一、两列布局 1、前言: 2. 两列布局的常见用法 两列布局的元素示例: 代码运行后如下: 二、三列布局 1.前言 2. 三列布局的常见用法 三列布局的元素示例: 代码运行后如下: 三、多行多列 1.前言 2&…

发现了NitroShare的一个bug

NitroShare 是一个跨平台的局域网开源网络文件传输应用程序,它利用广播发现机制在本地网络中找到其他安装了 NitroShare 的设备,从而实现这些设备之间的文件和文件夹发送。 NitroShare 支持 Windows、macOS 和 Linux 操作系统。 NitroShare允许我们为…

新世联科技:NG2-A-7在DAC空气捕集提取CO2的应用

一、DAC空气捕集提取CO2的介绍 直接空气碳捕获(Direct Air Capture,简称DAC)是一种直接从大气中提取二氧化碳的技术。 二、DAC空气捕集提取CO2的前景 从大气中提取的这种二氧化碳可以作为循环经济的一部分以各种不同方式使用。未来&#xf…

ABAP开发学习——OLE常用方法和属性

ABAP开发学习——OLE-CSDN博客 OLE常用方法和属性

如何学习Java“高并发”,并在项目中实际应用?

高并发编程 提到并发编程很多人就会头疼了;首先就是一些基础概念:并发,并行,同步,异步,临界区,阻塞,非阻塞还有各种锁全都砸你脸上,随之而来的就是要保证程序运行时关键…

Echarts使用柱状图实现横向数据展示,实现为每个柱子设置不同的颜色

这里使用echarts柱状图实现横向数据展示,同时给每个柱子设置不同的颜色,给柱子设置背景颜色等 话不多说直接上图吧 这里直接贴上代码: option {backgroundColor: "#1C162E", //背景颜色tooltip: {show: false},legend: {show: …

JavaScript重定向对网络爬虫的影响及处理

在网络爬虫的开发和应用中,JavaScript重定向是一个不可忽视的技术挑战。它不仅增加了爬取数据的复杂性,还可能影响爬虫的效率和准确性。本文将探讨JavaScript重定向对网络爬虫的影响,并提供处理这些重定向的高级技巧。 理解JavaScript重定向…

动态与静态网站抓取的区别:从抓取策略到性能优化

引言 随着互联网数据的迅速增长,网页抓取技术在数据采集和信息获取中扮演着越来越重要的角色。不同类型的网站在实现方式和数据获取策略上存在显著差异。特别是动态网站和静态网站,由于页面生成方式不同,采用的爬虫技术也有所不同。本文将详…

架构师:构建高效团队和解决技术问题的指南

1、简述 在技术管理领域,管理者不仅要深入理解技术,还要关注团队成员的成长、有效的项目推进以及高效的决策和问题解决能力。技术管理者在技术与管理的平衡中,需要能够清晰理解技术背景,制定合理的策略,促进团队合作,迅速应对问题。 本文将探讨作为技术管理者的常见挑战…

浅谈vuex和pinia的区别

文章目录 介绍核心概念用法区别导入stategettersMutationsActions 工作原理优缺点 本篇文章主要展示vuex和pinia的区别,详情使用请看博主其他文章或者官方文档 vuex官网:https://vuex.vuejs.org/zh/guide/ pinia官网:https://pinia.vuejs.org…

python的json库的基本应用

总目录 一、json库的介绍 Python 的 json 库是一个非常常用的库,用于处理 JSON 数据。以下是 json 库的基本功能: 编码(将 Python 对象转换为 JSON 字符串) 解码(将 JSON 字符串转换为 Python 对象) 读写文…

R language 关于二维平面直角坐标系的制作

昨天说参与了机器学习的学习,今天又来讲讲这一天的学习,主要是做简单的数据分析和展示、 首先,基于系能源汽车的流行,做了一组图,如下: DATASET: 1.比亚迪海鸥,磷酸铁锂,…

密码学简要介绍

密码学是研究编制密码和破译密码的技术科学,它研究密码变化的客观规律,主要包括编码学和破译学两大部分。 一、定义与起源 定义:密码学是研究如何隐密地传递信息的学科,在现代特别指对信息以及其传输的数学性研究,常被…