Redis二进制安全

为了便于理解,举一个例子:

在很多编辑器中,都会默认/n是换行字符,也就意味着一串字符存进去,涉及/n都会做一个默认的转义处理,这在编辑语言中,C也有这个特性,例如字符串Hello,\0 World!,如果求一下它的长度, strlen("Hello,\0 World!"),返回的会是6,因为C语言中默认\0是字符串结束符,而这,就是非二进制安全的,因为编译器做了默认处理。

而二进制安全的意思是,不会对存入的字节做任何处理,你怎么存我怎么返回,如果你用utf-8编码,存一个 字,占 3 个字节,用GBK编码,占两个字节。存一个 10 占用 2 个字节,存 100 要占 3 个字节。 Redis就 用了二进制安全的技术,不将数据进行任何转换,以二进制的方式来什么存什么。为此,同一个 Redis 服务的客户端要统一编码格式,不然数据的读和存会有不一致的问题。

二进制安全定义

Binary-safe is a computer programming term mainly used in connection with string manipulating functions. A binary-safe function is essentially one that treats its input as a raw stream of data without any specific format. It should thus work with all 256 possible values that a character can take (assuming 8-bit characters).

二进制安全是一种主要用于字符串操作函数相关的计算机编程术语。一个二进制安全功能(函数),其本质上将操作输入作为原始的、无任何特殊格式意义的数据流。其在操作上应包含一个字符所能有的256种可能的值(假设为8比特字符)

特殊格式

Special characters:Most functions are not binary safe when using any special or markup characters, such as escape codes or those that expect null-terminated strings. A possible exception would be a function whose explicit purpose is to search for a certain character in a binary string.

大多数的函数当其使用任何特别的或标记字符,如转义码,那些期望 null 结尾的字符串(如C语言中的字符串),不是二进制安全的。一个可能的例外是该函数的明确的目的是在某二进制字符串搜索某特定字符。

数据格式

Data format:Binary safe functions are required when working with data of unknown format (otherwise the format would not be preserved) such as arbitrary files, encrypted data, and the like. The length of the data must be known by the function in order to operate on the entirety of the data.

数据格式:在处理未知格式的数据(尽管此格式无需保存),例如随意的文件、加密数据及类似情况时,二进制安全功能是必须的。函数必须知道数据长度,以便函数操作整体数据。

密码学范畴

二进制安全是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改、破译等,如果被攻击,能够及时检测出来。 二进制安全包含了密码学的一些东西,比如加解密、签名等。

其他解释

二进制安全功能(binary-safe function)是指在一个二进制文件上所执行的不更改文件内容的功能或者操作。这能够保证文件不会因为某些操作而遭到损坏。二进制数据是按照一串0和1的形式编码的。而绝大多数的程序会给某些特殊的比特串赋予不同的格式代码,所以当用户使用一个程序读取一个二进制文件时,该文件会被按照这个程序的规则进行解释。如果这个程序所使用的格式编码和文件被写入的格式编码一致,那么这个文件可以被正常读取,否则该文件的格式代码之中会被附加一些无意义的符号,也可能会导致文件损坏。如果最严重的情况发生,这样的操作会因为损坏导致你的数据永久丢失。所以你应该将重要的文件保存在只读性的存储介质上,例如光盘。

所以根据维基的解释,可以这么理解二进制安全:

它并不像C语言那样,使用’\0’作为判定一个字符串的结尾,所以如果你保存的字符串内存在’\0’,c语言自会识别前面的数据,后面的就会被忽略掉,所以说是不安全的。而redis是使用了独立的len,这样可以保证即使存储的数据中有’\0’这样的字符,它也是可以支持读取的。而且前面介绍到Redis的string可以支持各种类型(图片、视频、静态文件、css文件等)。

Redis 二进制安全的体现

  1. 那关系到二进制安全,我们不注意时,会出现一些“看起来”摸不着头脑的问题。
  2. 比如,当 Terminal 设置的编码格式不同时,其 redis-cli set 的中文字符串在 redis 中存的数据不同。
  3. 比如都用 set k1 中 命令,Terminal 设置的编码格式为 UTF-8 时,“中”是“\xe4\xb8\xad”,用 get 命令取到的也是此字符串,而用 GBK 存储时为“\xd6\xd0”。用 strlen 命令返回的结果也不同,前者为 3 后者为 2。这是因为命令行工具会用不同的编码格式将中文编码成不同的二进制数据,然后传给 Redis 存储起来。
  4. redis 返回的数据默认是用字符串形式返回的。当启动 redis-cli 时加上参数 --raw 时,则能获取到 redis 存储的原始二进制数据,此时 Terminal 便也会对这些二进制数据进行解码。如果 Terminal 取到了不同于自己的编码格式的 Terminal set 的数据就会产生乱码问题。
  5. 因此,在项目工程中,如果有两个服务分别开启一个客户端去连一个 Redis 时,一定要注意编码格式统一的问题。
posted @ 2021-01-27 23:41  等不到的口琴  阅读(857)  评论(0编辑  收藏  举报