php - mysql的MEMORY引擎为什么应用没有redis的应用广泛?
PHP中文网
PHP中文网 2017-04-11 10:15:20
0
5
840

我看很多人宁愿用redis存储数据的json也不会用mysql的MEMORY引擎,请问是这个引擎性能差还是什么原因吗?我观察过国内一些开源项目也基本上没有用到过这个引擎,这是为什么呐?

PHP中文网
PHP中文网

认证高级PHP讲师

reply all (5)
洪涛

首先:redis的速度比mysql快好几个数量级。
所以:
1.数据量不太大 && 数据量经常访问 放到redis里更好。 这里的数据量大小可以参考redis服务器内存的大小。如果数据量小于redis服务器内存大小的话,就是可以考虑放入redis的。

2.redis访问比mysql更简单。

    PHPzhong

    先了解一下 MySQL 的 Memory engine 吧

    http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html

    看看有多少 Unsupport 的。

    回到跟 Redis 的比较,就扯三点吧

    1. Mysql 的 Memory engine 不支持 expire_date,我得手动删吧?

    2. 存储数据前,我得建表吧,如果我的数据不是行列的,就是无序的呢?

    3. 你返回给前端的是 JSON 字符串,还是你从数据库取出来序列化的 Model 类呢?那我为什么不直接从 Redis 里面取个 JSON 字符串出来直接返回呢。

    当然以上 Mysql 的 Memory engine 也可以办到,但是痛苦指数就上升了很多,说明它不是很适合以上场景,总不能用剪刀去砍木头吧?虽然也砍得下来。

    至于更深层次的原子性之类的比较,0 - 0我觉得还没到讨论这个东西出场的份儿,因为你会跟苦瓜和苹果比甜度?

      刘奇

      鸡蛋要分开放,mysql是网站得基础能减压则减压

        黄舟
        1. 很多时间存的数据格式比较复杂,KV方式然后存JSON格式更方便,容易解析

        2. 可靠性方面redis好一些 -- MySQL的Memory表掉电后会丢数据,redis好一些

          黄舟

          论坛PunBB(FluxBB)里的online表,Discuz!里的pre_common_session等一些表都使用了MySQL内存表.
          用MySQL内存表(新ENGINE=MEMORY或旧TYPE=HEAP)实现会话存储还是不错的.

          CREATE TABLE online ( user_id int(10) unsigned NOT NULL, session text NOT NULL, md5 char(32) NOT NULL, PRIMARY KEY (user_id) ) ENGINE=MEMORY DEFAULT CHARSET=utf8;

          其中:
          user_id存储的是用户的ID,作为主键.
          session存储的是用户的会话数组经过serialize或json_encode后的字符串.
          md5存储的是session字符串的MD5值,用于实现Check And Set版本号乐观锁:

          --读取会话 SELECT session, md5 FROM online WHERE user_id = $user_id --写入会话时需要用到这里查出来的md5(就是下面的$last_md5) --写入会话 UPDATE online SET session = $str, md5 = md5($str) WHERE user_id = $user_id AND md5 = $last_md5 --检查MD5,确保session字段没有被修改过

          写入时除了要注意检查MD5,还要注意用mb_strlen检查会话字符串长度不要超过text类型字段的最大限制(21844个utf8字符,下面会提到计算方法).

          用MySQL内存表实现K/V存储也可以,设置3个字段,分别为键/值/时间,比如:

          CREATE TABLE mem ( k varchar(32) NOT NULL, v text NOT NULL, t bigint(20) unsigned NOT NULL, PRIMARY KEY (k), KEY (t) ) ENGINE=MEMORY DEFAULT CHARSET=utf8; INSERT INTO mem (k, v, t) VALUES ('key1', 'value1', '20160906173140'); INSERT INTO mem (k, v, t) VALUES ('key2', 'value2', '20160906173140');

          时间格式时date('YmdHis'),添加索引,用于检索.
          键最长为32个字符,超过大小可以编码为MD5后存储.
          值最长为floor((65535-2)/3)=21844个utf8字符,
          这是因为text类型最多存储65535字节的文本字段,
          存储时在内容前使用2字节表示内容的字节数.
          除以3是因为一个utf8字符占用3个字节.
          floor为向下取整.

          要存储更大的值,可以使用mediumtext或longtext:
          mediumtext: 16777215(16MB)
          最多存储16777215字节的文本字段,
          存储时在内容前使用3字节表示内容的字节数.
          longtext: 4294967295(4GB)
          最多存储4294967295字节的文本字段,
          存储时在内容前使用4字节表示内容的字节数.

          另外内存表大写max_heap_table_size默认16MB(执行SELECT @@max_heap_table_size;可见).
          可以在my.cnf里自定义,比如设置为1G:

          [mysqld] max_heap_table_size=1G

          MySQL内存表索引类型默认为HASH.
          HASH索引的查询效率要高于BTREE索引.
          使用Redis需要额外的服务维护成本.
          虚拟主机上也无法使用Redis服务.
          PHP连接Redis也需要额外的开销.
          所以,MySQL内存表在Redis面前绝不是一无是处.

            Latest Downloads
            More>
            Web Effects
            Website Source Code
            Website Materials
            Front End Template
            About us Disclaimer Sitemap
            php.cn:Public welfare online PHP training,Help PHP learners grow quickly!