Tokyo Tyrant(TTServer)系列-介绍和安装
2013-01-07 10:57
387 查看
Tokyo Tyrant(TTServer)系列-介绍和安装
Tokyo Cabinet 是日本人 Mikio Hirabayashi(平林幹雄)のページ 开发的一款DBM数据库(注:大名鼎鼎的DBM数据库qdbm就是他开发的),该数据库读写非常快。insert:0.4sec/1000000 recordes(2500000qps),写入100万数据只需要0.4秒。search:0.33sec/1000000 recordes (3000000 qps),读取100万数据只需要0.33秒。下图为各种key-value数据库读写数据的性能测试,可以看出Tokyo Cabinet的速度是非常快的。
![](data:image/png;base64,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***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***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***PY87v+Y2f0F1wKyA+hxY+oBR2Nk8U2OfJT0aM18L1G9jtrb2y7cbJw3DKHhl23bD58B+HnZcwUMqoQlwbHZbaAPpA0g2CzCwTrw2xP/RdIXRm7UMhfwUmjmyTXZl3OV4b8N2mn2DUXpfIn2PwS54RvPTjYkR+oSuEohjNIaAXsG4ngfgcClCE/EKkeUQtyTlaC/Er0CP49ZxN4mesnW2ttD5ysYt8e+YBTwVjlFPkfykyhzZ+PRAF/pzIWrCJtt46MLoF8+2UxWZtBr5DP6Doh/h2Cn/oO7QhRxqUGxY9APgMUV5GTJZsf2EuHVVnoEJBTG9gH8inoE6BfIR9EqkfUgpyTlSI/ET064CWzX5WrsZ+lYm0PnCzIRHZCPqKBYXBfxUyRKgpCkOXcm2ZQgempiaUQ+Yb4kdPMa96OJuh25gJv5MvLJr2lmf6fgXyCuO7nB29Hs90Azt7dLBld+hi8at6OPrlPLShwslLkM7dALkPTchIso3vHtgdOlsUZOxnnlrdDoFTIfwEzhfpVoIKBbVhIHJHwh4UvMPnAaiu8Hf2ypsBbsPmrN8onkkM70mfB5oOy4uf2APiSf/kJ3s6Bnm1URklnuAdhgGfwPMPmH+jqRFVQIT/McB9RC0JVG35+ED0S0ywvrK084YfjLbbd17A62fziDc7Cq5gpWtUE7cpmuEZSgR4uj2LASo2dn0AfCIOBl61qOk1eAkJ8MzAZBV8m2VtBShYzHell0P64HhtDz796N71kMFUEFCE/rGpyjWX7LG+HcnC7aW1tJxCpHlELEvLrrBoXPSLTjMJIPFRoZ6v4SdttIwPeTquzF3wnC+ZWgPoUzJSz2JvPV08nSz0f9Cqhd+RzwkcDKE4WnyKWRPzQPTjIT9zJcgIU1YICCct3svjj/tNOjJMlJ7aUWlAQPcKMegpcYxbBnSxxsrztWv7nihA7wAfj94he0DFw3+PqH/nuad/68aqCHyz353Cyvge+L7fiQSDcwvfl719V8GPlDpysbzMgHgPC/cDvP26nZV1e1eDv4e18G9w/w8//UghsWdkekl1Gvk1qh2voge/aA+nwGThZL397vOrlP3g7YSB8Bo2qz1CHjx4KA/J78GTaZDH4+R8N7RvlDchvA9se0lxFfnDwKJJiskF6bFEwiHsVYdPUHuhM8e9KMsGZl/X7OmPs+Ta/KTJxropdjk+mxMRjV//IT3SygjCWf/RxOlncXcLGUhS3ekAnyyW3tpXkVRJyKsYVzrl3AtZO6FyyXOmDpfS0a8gvccQkzuouJzjEOMoG2UajCQYlCfxxTxkjZuevQpYjlRu6Bw/UTGHVxcnKb53frTP9lX6CE0CxVxeLRIADuCg2SAu0B91gO1+39r886P9q3Uc1fkulxHJPg9m1PZizWhbpibIujBU++jCdrOMs329AHHFO1iM6WS65tQf15OAbwUH9i5gH8rc4N9dj93mqMvWQPEVKT7san78ifkeAb76uZIMi8iEYlCSw5zwvGCwmdQfcynOJo9zQPUCgzY+crID8S9haUFbC0k8m60USkVOiDfgChyrjkP15ySpOrF63T0JPCGCXWlCPe/ODnu9prnVt38iv6WQZEMJHH6iThdNcx/vq6O/7z1J2ya0t+cOO76D+5YwrxqXuLLQHYckS5vIUNXraLT/f9BkS2aCIfKdluYCDPWkolSj9G14ToLme3NcRDxH5HE6OfKr85NkcofcKVWMkm+X6via3VsiHepbzFBc4Gpk+mdl/vorIQ1RNWU2SzRTgpli2d7JzJ9k0CBPhu0WGAopVNstx8jJTTXT3BK+VUIkcyOfhy8YYW3uUXMeWVsl7R35TJwuOQPqR+wV3nGl8Y4imyhFTK6X66H7NFOYDya3dGIBWO+xirLUzrqRQISq6FeokLKSo0dPaIb8ST0EQG+AiF8QMpkEd+IGHi3fASqwnOZDAQCK6cg8UhHx5LxZkLztOtzufQf5BrCxxtfgx4vNxvr3b/JkjfzUqwWaJkqJCvpl7XWiKSQctcHMBzuL7HK8BZGPCRMWUx1MzlnmB1iI4+i0MG6SgHNGKR+2/IX5U8kJijMXD+u9pr+rUt82v6WSZMFby0cfoZI0ZVhu0qhgt+gDyK8mtg9HMg/rX0RhXFodsWki8FKNp+mA1elpX5DtkKlpWavNplqfmZsznsKC9IF82HKMteDtCPjAuMpZxtTQCORj9J444N5svVcd5HfmBlm7IN+mgFeV9JTDBeQLqrUh+vD4ozEKbDmhDUysgH1Xg1ygXxZRvhckLGWMsyFR8LuRXOlkUxkoUpT5EJ2tvsZPGhZW41QPIJ46ZDzg1QdAUf4CJ4owrQz6lQXWtw0uNXJWUntYO+YlskBlLgsRkU1Lkv8kyAxaRJ1XJDd2DhODtqLwa8jkDUSHRD+df9Lido1Uhf9JAfi5/RS8s4Nmlg8DQLQz5WpxBJnXkYxwB+XZYiV479nVAvo121eWTeztytStv54N0ssacUUxXfXk7Jrllsih+Qf0rMK7q3k5kowV9sHaaKRHYlWzQFeQXcjtGRI2pcMIBiHJDdyPfOFmnNt/IWOJqcRgStjTxjnyb4Z7zdtYj5ijk41+TDsIvqxm8nVUOaw+qoiF/Eb0djiPwHQMHYGbeDvKRtwNrT3khY4x96hmuC2NVk94P0skSM2ZaVjPc+21+lNwqOMU1f8bUv/gaoL1PZric6koH0lLU6GntbD7se5ANish3waDE5hvH9f0Nzj5YVOt3gKBxX0f4h1VN5hYvqPzAs/HjRsIMF0uWgKLRtQjAsKpZm+FijsLxoFVNy46U9KyYTuey5pzc+gzXhImgsjvK8CJj7sh4hQyM9GgzXKtEjlQ2w+Vc53OvarowVrXQ+UE6WRuedgWvPIpb3b+2EyS3lkD6wZFv6l9CPia2yaqmkbSAfEtRo6ddR77caON6m2yQ4cVWxikYVCXQrxge5HHNJwWAIkGh9L6OuIf70PmOrje02cmKeVIp7/36VtUn3skiJysczxQ3tz5IJ4sH/tErD5wswieoMnac0rvklm2iFuJkBfWvwLiynSxxsuyEq5giUrTw2S2b3xVKvaZ/PvK7VRfD2Xaxn3h1BELi6j7466sKfrDcgZP1RDB+aNYPAuF++L+q4MfKHThZH4rOZxb2GBDuB/4QpRz6znz54Rp64Nv2QGomBmbKM815q7wHm//Ae6vLrcMMtxUePy7RgPwu8H0g7YD8jwN1q5IG5D+A5i63/nDkd1rPd+T6cbStcNw9Uf/ILyvxHJ5MxvDewNDAIWtBV6f/GW7CHeFZZ5IlQlwUfzq7REDt3GBjtSS5I4ZNzQhqQaEwlucCQqYnFIgqZ8pt+PlhbtOOk1VtcGF7k7uu2PrMsAHGixFh3a+XM1PUiJOzN/3Y5u7taXNHZyDcsnNb7OqUfqg2A9cQNhYYGrsx4rzu3FG6VSwCyiruyAqbSgw7wN7kMc913Gtx53mezmpJcz9YRHJQCwqFJR+5nlAgqtxEfmdOllG1GKpDEhQ2cLnXz2jm1dSPOm7z7Ks0H8dMuRJ0cKpItNbu9JOu3pGvME1nL7k8UGBoUEHHtv3vsb03sJ9yRxg5yVAdHjCLwHpnl9xZrrZl09w35J+wADsePxRWfRT0hAJR5SbyO3OyFLypMOWZBStzx9Pi+C10reP1YcwU0l1QNyObiKuCYJw3xslN3yg1xDidIssnGWKa0ZwWXK6OLU1G+01j2jGBGHqKX4ShNXkgZ2hYNFe4+h5yKXekQMzOZrxfU9HKL7BL7kS+ot3S3EkHcY4K1YK8sFAQPkr1hAJR5Wb0QidOFlFhscszi9KskD8Z3YGFD2OmiO5C6INsYlyV9Vs2Q0hm/g5PeG2xmdALyxGwiSBnxoQ+6+obgAJAEHBwJrYzNDYZxvrz/Hza3MAdwe9L2PpsM5OfX7FL7vDzY5xnyB3uzQ4niWN8B5UgFmaXfUSxpKV5fMHJaon8lpwsOPRvuUK6QIriCKiQT/WJzlew+U9npkTks8LiqjD8GQBHuH4+9Xh8/AnPhzSXr4b8gwRkiUSXBzKGxpYoXAVwPmHIpdyRklMMnmDu7lVUU+lcbkB+zJ3ck7VNV6gWxJEepXLto0pPKBJVOiPf0EtUl1PE9NaZKfiYsoRCvoLqe0L+85kpweZjrce5KsD8ZeQbEfMpV2cgRP/h4i+7pQP/mMoD5eWG3s4uiAU+oeCEO7KlTdZEe23KhsEB6762E5BfY6YcPFeRblRYvJytayScSFRpifyWnCxxueUJ8J/Jm3TYzM+/39v5CGZKavONq0JrD+S/w9t5C95OtPlfaoZ7pD7aTm//IA8UGBqc92r2x6t/5FfcEYoTHtdbzU1hnSO75K5yHfl1ZgpyDWpBXphsvwsIcSqv90Aytbm1nu/Ek1acLJlmU222ow0mj89wg1pQZV+fwUwB5ZxcKpFNjKvCaS7WoMvpG9QDwWXhDJdLtPhv+rVWNfc6W8Tmsi4PFBga0iIHKJ6D/IQ7cuDAg43GiuaeGm6Yb9/vZVnIfZ2ZssOCTlALCoWx2S4g5HpCgahypr2ncTuO/FacLCF/nhXwkLWIicM63OYXE3OCOl7Pj8//ATtZYupjHZ3MlCAPFBga3NgKnlDfNj9wR6AWtJf9gv3lDJs7SjzyLLBoO5brwkNNZgpHtqkFhcLETHEBoaAn5ESVFsjvwskyqlZZQm2ZW1jE1EIMQV7Qbr7jej7y76jUk2/pCITUoX3s91cV/GC5AzPlyYD8sOwfBML96H9VwY+VOzBTPgyZzy7oMSDcD/wnzHDbVeZVDb41w332g76a/+DttANPL6k+BwJ7aUqrTC4j/9tScYaGDT2gHkgHyMDJeuk7joW/yvQO3k4YCJ/B0/gMdfjooTAgv5Wv8niiwc//aGjfKG9A/uOgbpXDDeQvsAeBo7HDsjwJJjxEjSv0+Gxk+1NcvreDNMNXOmacVwxwcRkhneynIF/m/B5PqjwPh9fY/Ba7W/F05jbDZt5pL+MJyF9XwSrcRQIuKgEh/fmcPdwoDcTNVNsy4/6TuFkPqAXhbgbgpbk7tSyQz07Vgo77lWI0sbHFoLkWO1lz25UlUiuCScGwS5wnybB1IXvmR+nz3Hz76qKMEKQV7K45FYAU7H7l6pWThcE20qH/Gp84A9RUoiblaORqEDZ8b0UgnyFpNZvQEBnqtI3XO/K56ZnE4fMkzURAqDpYs/eC4yGaBDrCJMgNUySlTgGMByF3L7dgdFqSu1PLAvnsjFoQHoji1SqliRunC0odiwYfeK4IJoL3mpEJ75DlQdBmXkc+vrokI7QSX2WKk4sN85ObyO9PLQjALxCIiVAiHhf+ztcVoF6i7u86CncSDv6/ZcfPkLRObqmJDPmh6rfyte+7A+H2u90ZWXr2Ct6iocdGv//5HJtfHZzsOg5jyBSFut5/oixC3pZAfpq7U8sC+eyMWhBFI1j0ZSZOY23Hg+oF0yrk0gw7I3PeIaaDX1cNm2/Mw3MyQiUcHJ34/W7QuBH7FeLz33tRC1ItIX1i4g5vGNRCPs4ip9jKAnH4vFB5uGTUIXrDwcmKVZMiUUrSwks7KArhu4lpgzHlNJsjrl8iQxIzKiAzhAJG7UD/Acgvpd4Qz8+3P5+D/FQtSEMPAj6rZWYyPvefIn7crLZAfpJ7iL8M5LOzakGG/CVkC8/HCzWQP3XTpTOSZZ45FuQlTEkxf6fFxInx+BfvEyCn+uqCjJDCeBDkG3K+DgkhXx5JD2pBK2kY8l8hf4bXFbJmA9AMlOOmnJilEtD6HceKl2Bjva1MkSglaXHMmKIQuFpIw/zE25pCK8ZEhkzMqJhyaHXRFX2qzUewMKEe1IL8z+cgX2PKCSNLeOYl4L+EdIqgfz/yEXNN5Ce5p9QyDIizakFm8/eYY5TGXbnh7UwuIB82v2Dc8jv4trTbdZuvr+o2P5ERgjYDBlIH5PelFhSQDxhH5OPFMwViRb2qkL9esIpS3RJmbUKfkrSIfFMUQlCeId90VGgQTGRIY7wsNIX4LMhnpH5E/moZ/nwi8iUNRO022PpZuaeXJfr7/cgv9hXyLfeEWkby2Xm1ICF/KxUJd3muru3AwmPdBtKAp96OrP87WLcroLrh55uTdE5GaC6qImiuYUxdX0cJ3k4/nKy3OQANlbeat8NqvsPKL1aOfHg780kp9RV4O4Z8eWYpSUvIl64K1CTsRBVHvukVEfkmO2CidtdfbbVvn2nzObPkeHRvJ/z5HOSn3o5KGBsFRp/fjXwFKWOBJsm9opYZ+eysWlA8XCVSdK8if5XhBQ6PmIarOcM15OPj6AnxQQvzJ8iPMkI8x4B8P2PpwutOxVBO4SHk98bJmkPHKOdkNp3hrqcTODUlFIQc+Vhync5LyMjNVjhjAdyaeWGKRClJq0J+pGe5t4MGmciQiRnJ5n+mGa5sfiKR+zw/P52DQgv3uJkC7/B0HrT5MvL1GW6gljn57IxakM9wRdFqZfMxS+NSiPi2RL4RTATv4g1+Dh6uVjQb3g6+qtv8KCM0l+4KV3TetbR5cohTHf1hVbMntaDFW8YFTK1qoh62qolTIsCWmEDw1jclqOL7thrl75i72uTWZ7gVSYtKeHgZ4r8p5IhE5wozXK6GSWQIU2DOcJnpa1c1aQWTNQ0ubCermrbOfer3hk8f+JmsO6IUsqY2lDKR6X9kbUeiP+mqplPLAvnsjFpQQD5WNcupU3Fa7GQRLQnBxLerYD/xWCGIiUccQBO/uigjNJ8jjZl7wOcWn7X/nSzXrrvqfbTYyaru51vrxilar97JEmPoIE4WAIPf99VOlv35HOT7XhM4Wdp24ujDohhPOXFe1Z3lcrUDsrfIEllRLUhnJu6PgXwGjvuJWpA8JO1kaSPtdKSfjVjLa4vTHVzWh5P2j3ys0Nxx+smVhlA17rrL1rEXnuHntzLcryr4wXKfyclaZMXT1aHOw+MJyO+Iw49P/iAQWoH8bKJXFfxYuc/lZE21Ev6Ca0D+/UDufOdjCOxcXLzhc5Sbeju2fDRcQw981x5IR+vATHnBm62xnnW/9Xzszs9hex9rQ5e7h/j8l2N9QH4XwPaWdkD+gPw7Vxd7wuDneNcM3s7Lx8ETgIBVdKdj+CniiCQzsooTNp6znn/AZkEIiIdqj44rPxSqCeJ4Imegc4ON1RJJLtgV1kTkEKWBUt6LtT2kaM9MEXPqYU5WJSM0NS0VfDCyA+e4R3z5es3aTqedLK98f9pZnYFw0/QWOEHed3ELRA/MltpJIvIDYeM5yAcbZeflbhFJtkUEAx68kD/L95s7T7INrBYnuTA3ZbmKakEp78Xb7inaM1OMjtUDJyvKCOF4VkU2YMN/xT2lxci2/i+u52uAkL+1Zrzn1UsxFEqP6GL8W6VHIAEHXD+cLGT0TO2s3pHPg5M3flQ49KIsvjcMhSqQq/+zFxggo3holMkfGAmgBuh8WwwC/n/fiLPIhyQgQ1keolpQEhsR2u4p2jNTeuNkRRmhIkdsmDFShPwQunYR+S/kZF2hJT5RO6t35BdBAs5fDhAM+hjko5SdB8OvYft32m2VUNE0kn/xR+cGW5xnJLlYszxHqgUlkaBp25miNTOlN05WlBEq5lITqpC/vmb0X8nJkh+plwhoVsbSGo0KBC6n2lkQ1noDc0UkNUUjPX51BoID+uIPkGzGkXaNVtl2v7shz7T5jJIx1UI52lTtceSPV2Qq+1edG2zIjyQXZWOnpAe1oBgDnbSdKdozU3rjZAFFJiNUzMXqTZD/Nrru57+MkxXOVyDNylhagM0cYaOpdhZ0MqCFR25KXwpCnYFwC/kz2luKEvq1FPQ/AvmAmr1gMJMuV2MDLGz+nrPd7d1aLcJ1RXJRAVOXvzC1oIj8pO1M0Z6Z0hsnK8oIAfnUUumC/FdxsiLyOckQS2ttTMZUOwt/goJC1H9a5Of0dqI+BJ1g0TfM5D7V5jP/mYrJCUwNOXk7Y7k8Phg7D/WK1RK1tkwJSCUx18rmx7ZXKYJ43MdwsqKMEJEPLZWO3s5LOFkR+XhXOUvL2OsXkP9ZvR2BW3QQoA3g2zC6/QOQLxpKaeH/OHYBK6kR+ZrmnmeIBARf+ekan4HkwpTy56NaUIX8qu1VilbMlL44WZWMkJAPLZUOM9xXcbJSm28sLTKxwKpJtbMqm3+La9B2BtDZBN7Cyh6P+uDan1OA3rQJn2/zSUMJXhbXlHZahhfoN4isXz+2tlORXNganRoUpIGStZ2q7TFFS2ZKT5ysSkaIJx74OqnWdubG37qxqvkSThbntrZMmjtLCwdVYdZRJNpZ+NO0s/LetLN6R/4RO0o874DMlC1aQ66qk1VExD1/5tit8dTie64RwKcSM4WqPRTHYoEUixtfOv3jZr6B1eIkFzFTbDwFaSBPIbUgb3uSoi0zhTtZj3KyEhkhrrZzootTd2wnC9TY68hvaypbpuudk+XlfuadrJtgsgT9D7l2BT9Y7jOZKQMnq+Ww6iXZg0Boh7ZzqV5V8GPlPpWZMnCyeoF0y0weA8L9wP+qNv/uFreJ1Rw4WS1R20eyAfl3Y7nbjZeR/12ZOEO7hh6wHkhHyhCl3IfZfiiPweZ3M913p27j7Tz0JB+5+TVRyo/U+PF7B+TfjeVuNw7IfxysveYwIL8bgO9OfRX5Uf3HOC0Z9u1tcZ4h8Hre8/iFM00Y3mLXyk9gQpKpRfW+x99aYuUDbX4bOkqXI5GLew9qeQLyK7WgwMmquElPVAsKBCzHJiV++lALGttmmPDmRyOiOQzXwT5doGtRmogXtszs1PJcO2mVStKNU8Sj+g8AT0RPtA1lNJOw98pd/fV0VEI+gQdu4lhxv/I326/Fv4vRCL+9YbQU10IzT8ZDOFezF2ZKEAfS0GWONpiNv3JLIqih/3N25I5qxxLNbxFpLoz+3pGfqgU5JyvhJj1TLajaHwb2JPHTh1qQB7px1/ZgYXeIjdiDXXlgTAROzQzSRPhmNwP4sYfsekLJeaKtkC9hICF/PeXRwLapTyzrI36ByGMAXEfNRgzNKE+C0aLgZKQ2jbhO2moxPp+FBU7WJUgtoOPAZNTvmoBGWSGLwhC8XByIUZXYo9C54Fb9NsH1LY5YZH7VdY1sdgH1quTdr+/LN8YTZQMnKxKaJB5k1xMKtqACM76U+OlFLcjqLtDbINiR14iTmhWVhxGgkDTFyEWalusJJWdIt0K+hIEM+XNim8gvoDlVIb/EOdvEd3pmZTGXoApEqHKSORDcbpTbW9Y1BUW/zJQgDqR44neMDCFfh2KqhTrqdpJBxO4dhynjt2mQBDL9H2xrINYu59HJSDVxWbkJNCLmeNNBFw/54RDleYk3CjLhqdF3XE8AYO0s5SND5gM36ZlqQTTGEfkm8dOHWtAun0pmEdfGkO+xmzuVhlDoIE0UxtwMY8OGS1RJOh3pzVXNSv3HkC9ClbwF/ARUCB3+aedkG/JNN4hHZ8vKQ24KtJQFvmzjStehIuRrUtGDWlAUBxLy5yOrug1HGHQe6g8JlDnOy8fh5u9zcKygmmKSQKb/w5GyQMuzEvIT9oKxQ/PzGc5THxVvCGbDEIK41mgF1r6UWbpfz0W+cbICN+mpakEp8l3ipw+1oC3wbeGmx6XTUaY6JflQws5v8XuQJlIa0bSCnlBQSdI319d27Kh8qv+kyMcjLac6VB+X3IWJJn81mw9IFeb4Fnk+ynCU/J3I74uZYtonEAeqkM8Ju7wifrOaZZBA4cxdmOWweHNJIFNBIfKpBzFalQH5JpRCcQvM4cs3nKmOa2FKK58S+WYVnZv0XLWgFPku8dOHWtAKcJd/A+fdrTqmrzPS0jGsVxBIdGki/xLu/y7oCQn5klBsh3xpoDS8HbP+Efml1BNS5NuiD0aFubvTOWL99VuX0+SDt9MPM0X4hjhQzduxOgPPq7eCcxAc618Y8jVqTRIoQT4GCpA/pTuEy5GPwenIt9mFTXA+qbdjnCyMADggus7qRgXcPPQzeDtB4keZPaYWZPWRIJC89nAFzlUQvXZpIn6dr4KeUCdvJ6j/NGe4t5Bv0wLqAgpB0BbU7DiMBBs1ty4hvzdmitn8iZC/4JIrffwZ0K4ZLtUQMSqg8jiDt7OCkN0aoceGfNP/kc0X8qPIkXs7qKK8HVj7AiKppSH/VuvOf/9Ub8c5WYlqzvPUglKbj9/p5/ehFrTESqbZfDo5NoZnGAZL5I7xQNFdkybSKCP/LDfXHzd1neFSGEg2H6fYcD5Ia19KN4iXvB37IrH5kAzEVSIppnwAGlVmR/AkSh5b1foKq5q9MFOCOJBWNZmjDJ5bZtDLsSg5nc5lzTm59RmuJIFM/wcTFvwxgxtEuQgTSqEILmYi6CDMcJHKZricAH2aVU2ayLCW45wsspecm/REtaBABzF4UuKnD7WgHPDOae338QC3Gfw3+vgogatJLk0k5KOhpLoHPSG8K5wfecPPj+o/vpPFFcrqwDQZS3thaumSqX0t0Q564pfTaUHWEl8dPP6phuGbI+CT7WTF+q5g5N+vb1V9op2sRC0ocLKias4z1YKcgEVOlrGxALvH1YJ2MDRm7DWeycni/hTdH6CUPBWXJhIni1wwab1LT6jDTtZNbD43wQciv1tDYPefJSPzDG8nesPXfnlVwQ+W+0xOVjdQ9Jn60yK/z0Y28noQCK1AfjbRqwp+rNyncrKe+JhvZD0g/34gd77zMQR2Li7e8DnKHeLzXzfMveRXAeEZ0QuthsOrGjxwsmyOPlw/rwfSgTnY/MHmtzLUPSb6fDb/5RjAivsnqMNHV+FVQBi8nTCaPwPqPkMdBuT3aN/PZfWqof4cTpaFVlqIpla++YHvetWj2K8C6wOR3z2cDltz90VjXh9L/QMh8JJsrwfXgRs82g56qk7WFttkibIJOVmBpuW8Kg2Erg1GG3hCIHa0xLbixX0qHpPr5LMgysXyvA6e4iM4WYgM434v9m6nimwoGeKVELtamdLPw8nSdvXJEaC9HaaZ9EZXINy0yIGXxIQNvain6mTtoQ50iHETxskKOlnVaf6dkb/iziw2bnVOroUpM/oS8UeBfBZEuTiyEdSwAw0xpGgdveCROPdwsoR8hSlP3hXiQ8ufhL21RX6PakGtOFlXwm2eKBH0TOQfEN61DzpZQAMUpSpu1BPPz9/SDEduinGyQihP8iroavNnPCc2O6x1briFMTB0Ya8QNQ20SpTruJ3x73VI0TVi7S5OlpAPjQjGLCqWv0K+iF2tro/nZCEsgZbdaFZiaSEM7U2vrjeEcCpCDUyDSYZofvg6fUkEPRP5RITJR9lV04t6IvJ3Y1h2xQXjck6WD4WEV9XZ5heMxBzvVXGPPitAM1ubXBD/rUS5EJ8JZgAOj/YUnaKUGXRGb6UrJ4tUqpmcZ0T7koteIT8GON9E/8dzshhxz4s0K2Nprd+yGYKRU4kgmIIcocqIuu5LKOW5yA/yUcJgXS/qichnYQc/JD9wshz5Ca+qM/KZLWRPDphC7CQHoxA1JyiacxVFuUg/l1aXp/gQThZt/kRRXRIAhd5CffjcRD0TBJvPOP/IQCc2GbTPsZVpKq1i+CffMxpyOORBTjmROZsH1nsLTlZEvqblZGmtwTFGNqlQCv5E9uKxdGEVt2ryUxjo5CUFk1/Xi3ou8vc6BIRYhByueTtyfypeFf7oPrGRk4P5Yy6XB+Nrhfdw5e1UolwMU0aEMGYEluJDOFlEvul+kqEBB+cRb+cDOVnB5uN15SwtYP4y8vtf3ekOhIDpaz+D1wFHISSTXtRzkb904CecrIqULl7VPcjfxvBMZ2WxSaZFJ5tfiXKZZCJ8Ik/Rydu5l5NF5JOY4tykyZsILNXRJa0M4MdzslKbbywtWnsgP5UIqmx+XxJBz/R2KvkoWd+oKKXDOZ6K/IJT3DDQUptf8aruQD5o88f1VgJzRj08aDDzKCE/diGKch2XTLCbhhRdZ7j3cLLIdwVXZbparIyOqBOmEmJXW+TraIeP42SBc8x3lGhWxtLiNBduZCIRBDfSJIKmX2JVs5KPIkAaelHPRP4SwD8kyJfDpSN4Iq/qDpt/4KtqedjDfQ/0Ko7hbeXtVKJc4mKFI3iQov1JU3dzsuR+wz/GuYKcIgNLOK4gIXa1wv2HRi98450s5yVRJ6uhF/VUnSySMkmSSjlZTtOqeFWdbf7eTrHcce7KZVNxsjjD5e+2TeeiXOJkuVZXSNF+J6slQp+V7AP3cJ/VhM75PsfPvzYH8O9eVfCD5Q6crM4Q+6Q3PAiEFhC/kORVBT9W7sDJ+qQ47l6tx4BwP/DvWF18oLDk1lc1eGCmyG8crh/YA+nIHZgp3Y10z3e8ygQONj8MhM8wu/wMdegZ2DezG5DfjxN1M5er8fk3H9OTEwzIv/n8+kvwqiH3Ocr9tN5OJ8GJJ4/H52bfPxCSRexkIb1g8ECgdNyxo3R7yPGsM49Q0Oo7t1ux5I6dKDvY8bGTbFNmCk89Ze44a804K34Km+rIhh64q4SfJYL3QpWu2vww60EQworblgs7WEyxYtxa1a4Cvshm3KKASIpdUztU//FzyGDz7TBDbgDXL+eJ4DTL80CsyfvwsHzfSMOZzjri2S+ciowMbMdOh2NmkzvPQO5rPPSO/HTjEpun+5m2VdeM2HfChoG494IRH3Yw6RLssO4UqwZg7hBbU5JREtgpd5abMlOgFoSw/dDQqpGxoQdjb20x+koddnjS3rrNL8GmQhRCOcGBwgTIPEJGaij4akXqyULoG/GfN/7D8F0Fqy1Gd54nHFBEb0fhkOGw/gRezhOhONDphQ/tQGO7cjvHFp/w0FvomcTrXSFnUyhTlCVOWQZxrOiiA9cX3JN87gTCZROcBKvsze4h7a4g8itKxxOQr9i4wjaaGGCzw8Yr4wwwIPiha1zdO+JSZgpPDF9P7VTx6bpqJEu2hm4q8lY8XveazV8BQIq5zNcKOKuCcon8OaIwhXydr08hOEX0lrnFJZuUxGOxjI78HOdyZzyymIZ+nhGaxhMhqCmLhaOPnUACGz55o0pLgXC5QB8sioVqx7GAmjsR2I9BNvsP5ONfKdHN71U17GcY9I78NECRUTs8v36/FEuronQ8Afk6J99Da+T1GG125wHT4Iucs72XR3D9m4SZIkGAQ7YLDQ2N5A3eUL7w5WXxnPGzMaKnfr4iz+y4eVzBTQB+REcy5IN75RYYyH+XETbkrx80+kI+YExxrhIKPutZWWC4QcrkHSqP8Lqg1JOvc+n6GIEE2j34V+8JDBS37vRnCGy3+YZ8T+xDU8j3SveD4Htz6R35NToGrSIhvxfyK0rHE5Cvk/ktgt7IkDT4iCEyx+MQZR/ua3DCTFEU6C47pA0N3rw3FOTdHc4a56UByevW2o4hP4+Cl3CJaTkBRyLckQ/YGZWJ/n2K/E4aoKdYiTbf7PUEWnOaY5TGE1HNctf1MQIJzu2PyC+g1KI0rC1/49SEghFCvsmdBEkfIb+mdnQvch+97z4gXDGVNToGsMc4LmfmVpSOZyF/myCfDNoQSH8sIhX3zgZXzBQhf+/INy0gRScT5t5QDjMbhAcdAXEP8u3BNmw+/A2b+wJ+5ni7+ewH+cyQyHyHu2/Z15EvJFsYPTQdoE9hNh8iJ0I+SeV6J7nnfxH55u2UXbQtHsX56f13AuEy9Gt0DNKxPagxGwfCxjkkXBlKLb+64O240a3UfB5osDFTmt6OOOd22fqIM7f0aohOVkubP3dvJxwab35+tPnzd09gfn6F/D68HfOwgNoZlNlKSrTBqYG3Y+JD9Hak62PIN6qIJh0R+Xo5cHLgyDcf6Iy3s84xwy1d3b1/TLfL8QEgnIdkjY5RytWh6YUDklA6nmDzz8xwpRYk15/yzGdtb8thBd8pMlOO9RkuSgiNZGbytKiSRJtPTbydLyq183bWlEcE0FPkG8CJIs4f7WgR08WFke1thmvqK3RU3rMcrg4kam2GC14li6J3ZTNcEUgWSIiBAC3GUTYy2VL4Opwh66ArcgzDqmY6w+V3bMl8FETR28H0Cal6R366qlnK4hsg8GtF6XgC8rmI01jVpFrQjpDFRkJwOu5cTU2ZKav6qmbVyKqhWE3luiddITEUT9p7aYaLKS6gX8TFRa1qBuQX+uuNX9qqJl1ownVOga1Hru57uNRuMwWrr3r1jvywwQNmysb2LfDYyUkBMJ3ScQYJrW3v5YS+kyVmiu9kOVEkrvmcIrB1uQkzhYctVDtZoZFipnhDqZKEv2wjyl2h6zbfuVVAUVS7wu/KgCYy7mRhDdGtqvLG2iIvLfE/cnVHPrXbXuunP9Je3ts/8luC6VUFP1juwEx5FHGf5f4HgdAS5meSvargx8odmCmfBbgP1+MxINwP/Dv97QcKfGyG+3DBt2a4Dz/JRzLo7u08UtrnuHdA/sOYbpfBZeTLVR+uoQe+bQ+kIyRZ22k3cIZUQw98ix64jnw/tPlcS8N2ce072ynp5fJo13N5nZTSY7G91H3I5Av0QB35CC8aM6h/dqnmCBnrpVHlST4Q1VjymKBUYiAtajv2E+Gvlz9rlaqXNgyZfOkeaNh8GfldPCCOTUv/WFu8HaUIHrx0wn/t0kvEDkX3a5+OAlfLuFlsJAX1U8+b5Q0JvmgPnEM+EDceb7PpfpvNeCiuAIjYgQP2AenOIEYAlKwVfq6z/DCe4sDosbbPkHiPbWrtVttPfQHOWME9vbVnCz4Ngg+w2TZOR5WQv90esiVIMch7y11HxrpiZzDfu/rRbopqoRR+hxzOFDsux7M99uOwsYfdNU/TKOqLPquh2n32wAXk77gtu6b2ivvQQCpJMAZV+uBUaBmX+3EhUsz+CPYZob/f5ZDLwK/6aV9M17sxznPHP57tqlgBk/leURXhcuRjiIx5GDDYQ17asjgWS5WJ8bfhbUD+9pifLfY4zlY4LTvH6aMH3mM1aBTVZwcOeX3RHriAfMa7AYoV8onL8aGJ/AMBuix1TimDI4BJEd548ae+MDINQL4sPVt8BRZDY44ckE8GJyBbIR9/YPgZ8ktuXbMUKARY7s1ioViDWsMt48g8eJqz0/Ev+sSGavfTAxeRD7Wh9sifeWWISQT5yNvhT3nzemsQ+TmQr2wN+Yel2PlNm897mshH/KshH37MdMdcGAQY5wppsfDzORsZ89B1Il9VaxTVT9cNuXzpHmggf80JIo7kJ5ZAIr7k7YDeK2/Hbb7CYolM3LYBxBkbqJ/2BeiYS/N2PNsC3g6UXDAKkqlyAZr+HkdDJ8i3gZF6O7ih5PjZ8+ZzxTIwm+znJb0vhHFbmkZRX/qJDZXvpwea6/mM1aS1zMb4De7EDHNNF+GKM1zMdnN8C1GpjEGvSFdNNUERMw/EfuoL/WMzXMsWM1xMnvMxJr7GJZM5l3gD11SXuBWz0+1uDHnL+gy3mGG2y7hR/D9NZrix2CMi88VE4z+op6VpFNVP1w25fOke+J57uGXp56186WczVP6ZPfBNkZ8eufXM7hvy/rI98D2R/2Ufx1DxD+uBAfkf1tVDQZ+qBwbkf6rHMVTmw3qgI/K/c1Tko20btss+DLV9FHQSq4nQnHDqcsh/eTGAslYDi+PEamZebhH0iYywqimSQw7ZRu1EIRazmfnlRigK6OxV1ivU+NNvsVozvuju60zDsRp7O7tmoZdbwrywjnuhnddKuniX9tltmfnSv9db0PJx3+6Gz53izB6uRLNrF3etuH96tSkexznDvil3j9D/PM6Te1c6Rlrq1UXLZ2yL/IeLqa1C8Yp/1qpon0ryvvXViEI9k3E8pfFans1CFW9x8dq17JUqA7bzwl0zDs39eLefbS/9e6s3Gr17K/kX/f4c8tF1sN97WmhA8DDO1RUKnYR5woGU0yksOzaZlEqArna5prDtOPJKlqeYOfJ32HnFxu7OjxtS8KZyx8nfue2UWXSo4jpDfCjOEGUFSntfWMin1QkVYgQnDfAYh7vgT5yvMlMEJ0LZWKtQa+wAz3D7bobbFPTpCf3GGE9qgaaMQo3BppZFlTGVC7CFPFuiwva7IkdDL9DQh5hQFbpF1Ol4r1rvM8TqLc0Ge0P5OkJWM7yw9mgn+rz+7TZb5dmGZal70evLGJyqdoa72HAPcBUGuQdOK1TiJNLz/yIRtidxLJR6VluM/Mfra62ux9F+UXBfrXYT+XBNAHOcRIvYMEQbMD4hBOIQzAo/WFJRHjEFlkqH1VZxnNij1RGmOtxqTDwh9pIh/QiwL92KM3jTcy/w7CXj7mGc2MWdId5BdcYLfTvd4vD/g1Ikd+HZoPzpBiXjYFEiH68UHKnFUq1WsdYIDkKq2ea4XOsWT6gbk3hS5M+2Ec4ebOpZVBkjc+w4l9DgGO/td0WOhl5QLTz81ArdznCAthqErHHCn8WNekMJvy3qc8RBYAyM3Ta/Laf7FWIEESCr7l0tN9MYE2uPgnd5wz3ANSCfj6VcXvqXqWZlWahnEVayRqg5Y0tUX+u4HxDcemrzeSojT/ibMjwss1AbeQwB+QA2HjL+slR2jm2M48RdBQxVhXw8cRznXB5wD6w53xEGbOV+xDlx/qeiQ/l7iSAfRz4i21Y6+wpBOLW7wCDQvCEiH4c3eqmqVVXrJQ6iyzj+ssLDPZXQbozxpCHik0k82DRkETNmDB6Qj4AgpLDfOe5DL7BTwiTXCt1Sp14N2mcFutBiSz1elbUvcND1hkFSWyDx5Fu8IxQkbt27QlkxONUeBe/i4WUMELEA1w7IR4vVs/agFEnL+nqrf8Bs/RT5eDPbw9/jEEYPMruAfJ+tpsg/MCmi1VJv54hj7srDZrpTrKZj2HInXALyGcbZQP4eZ08Hr1PJqrsC8nmUHa3tkghhqVb3OF7hcu/GVq5u8YQkxuBNH+JJNRTN5odgU8+iyrjMd8iffj5eNvpdkaMhKltN8fBTFSq/IyB/Cy/Q4kY9XpXdhOMZp5hZKLa7bH6L/GvI59BRBokRAvKtfh7mF5B/09tRL6lnI/KxLoHsvdU/ILj1jJ8/Btjy444moAQSqNegA934MvDHZjZfqczyRm+H5/vL4dAMl/YMEZgzRMuvEUW58Zkegzc9d+SkI3hDdGjN2xmDfLKhOVP59btyvEe22yn8fiIfBvygeTQKV61ireEd41M4tdu1brGEdmMSTxqQv7EgU5anLJKM4bRAcaoc71Bh+12Ro6EXCKQQE2qF0oYiF/N2AEaLG/V4VbUoP04dbUjT+DYi370d9EEMTg2Pgjlbe5BNYvM1t4Wvev5fFj2DzVfPbpDII2m9vnzcPyC49QwDvQBgNUucZStO0ca5LRsidJKvW4RJWoQmDO3pDPeAAGT4AVrVJKlLq5pLrGpClgoBmraqqbmccqcokBHePYxTE0KPDz3YDCPMcGt3rTRnZULkhbogLHPr0Z1hhmu1Xm1gl22Gq38sod2YxJPKb4Y3DnqlB5tykowsqozX2XQzXmHCgtvtd0WOVjNczEkZfhoKZWvjlH2MXPc2h7V4VSaDU1SQS4DpZAh4jd/ibuvmmc9w4yTYHsXG71L9OO9nAcxTfXxrVdMUC9WzcZrr9VWrf0Bwa8edLD6v4Rp64Bv0wID8b/AQhybc0QMD8u/otOGWb9ADA/K/wUMcmnBHDwzIv6PThlu+QQ8MyP8GD3Fowh09MCD/jk4bbvkGPTAg/xs8xKEJd/TAgPw7Om245Rv0wP8brqEHfmYP/P8l1uyXDOKRXgAAAABJRU5ErkJggg==)
Tokyo Tyrant 提 供dbm数据库Tokyo Cabinet的网络接口。它使用简单的基于TCP/IP的简单二进制协议进行通信。同时它拥有Memcached兼容协议并且可以用HTTP/1.1协 议进行数据交换。所以实现了跨平台,跨语言使用Tokyo Tyrant。采用热备份,更新日志记录,复制(replication)来实现高可用性和高可靠性。到目前为止,Tokyo Tyrant只能运行在inux, FreeBSD, Mac OS X, Solaris。
下面我们介绍如何安装Tokyo Tyrant。
首先我们安装Tokyo Cabinet.
#wget http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.9.tar.gz
#tar -xzvf tokyocabinet-1.4.9.tar.gz
# cd tokyocabinet-1.4.9
# ./configure
# make
# make install
OK,我们装好了Tokyo Cabinet,再继续安装Tokyo Tyrant。
# wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.16.tar.gz
# tar -xzvf tokyotyrant-1.1.16.tar.gz
#cd tokyotyrant-1.1.16
# ./configure
# make
#make install
OK,我们目前就完成了Tokyo Tyrant的安装。安装非常的简单。安装好的Tokyo Tyrant的启动程序文件叫ttserver,所以我们也简称ttserver.下面我们简单启动一个数据库,测试我们是否安装成功。
# ./ttservctl start
启动完成。这是自带的一个启动脚本,你可以拷贝到到任意目录,修改里面的参数。
# telnet 127.0.0.1 1978
然后我们telnet到1978端口,因为刚才的脚本默认启动的数据库使用了1978端口。
如果顺利,你可以看到可以连通,键入stats然后回车,可以看到一些类似如下的状态信息
stats
STAT pid 24755
STAT uptime 37
STAT time 1236396011
STAT version 1.1.16
STAT rusage_user 0.000000
STAT rusage_system 0.008998
STAT curr_items 0
STAT bytes 4198720
END
请注意:在32位操作系统下,Tokyo Cabinet的单个数据库文件不能超过2G,而在64位操作系统下则没有这一限制。所以推荐使用64位操作系统和CPU。
Tokyo Tyrant(TTServer)系列-启动参数和配置
启动参数介绍
ttserver命令可以启动一个数据库实例。因为数据库已经实现了Tokyo Cabinet的抽象API,所以可以在启动的时候指定数据库的配置类型。
支持的数据库类型有:
1、内存hash数据库
2、内存tree数据库
3、hash数据库
4、B+ tree数据库
命令通过下面的格式来使用,‘dbname’制定数据库名,如果省略,则被视作内存hash数据库。
ttserver [-host name] [-port num] [-thnum num] [-tout num] [-dmn] [-pid path] [-log path] [-ld|-le] [-ulog path] [-ulim num] [-uas] [-sidnum] [-mhost name] [-mport num] [-rts path] [-ext path] [-extpc name period] [-mask expr] [dbname]
下面来说这些参数的功能:
• -host name :指明服务器的hostname或者ip地址。默认服务器的所有地址都会被绑定。比如:指定127.0.0.1这样的ip,就只是本地可以访问了。
• -port num : 指定服务启动的端口. 默认1978.如果要启动多个数据库实例,端口需要不一样。
• -thnum num : 指定服务工作的线程数。默认8.
• -tout num : 指定每个会话的超时时间。默认永不超时。
• -dmn : 以守护进程方式运行。
• -pid path : 输出进程IP到指定的文件。
• -log path : 输出日志信息到指定文件。
• -ld : 日志中记录debug信息。
• -le :日志中只记录错误信息。
• -ulog path : 指定存放更新日志(update log)的目录.可以用来备份恢复数据库,主从库之间的同步。
• -ulim num : 指定每个更新日志文件的大小限制.
• -uas :使用异步IO记录更新日志。(使用此项可以减少写入日志的IO开销,但是在服务器意外关机,进程被kill时可能会丢失数据。根据经验,一般可以不使用)。
• -sid num : 指定服务的ID号。主从复制的时候通过不同的ID号来识别。
• -mhost name : 指定主从复制模式下的主服务器的IP或域名。
• -mport num : 指定主从模式下主服务器的端口号.
• -rts path : 指定用于主从复制的时间戳存放文件.
• -ext path : 指定扩展脚本语言文件。
• -extpc name period : 指定被周期调用的函数名和间隔时间.
• -mask expr : 指定被禁止的命令名(比如可以禁止使用清空vanish).
• -unmask expr : 指定被允许的命令名.
数据库类型
下面我们再来看下数据库类型的详细配置。
1、 数据库名的命名方式被Tokyo Cabinet的抽象API指定。
2、 如果数据库名为"*",表示内存hash数据库。
3、 如果数据库名为"+"表示内存tree数据库。
4、 如果数据库名为".tch",则数据库为hash数据库。
5、 如果数据库名的后缀为".tcb",数据库将为B+ tree数据库。
6、 如果数据库名的后缀为".tcf"。则数据库将为fixed-length数据库。
7、 如果数据库名的后缀为".tct",则数据将为一个table数据库(有表的概念)。
数据库的调整参数通过数据库名的延伸来指定,通过"#"分开,每个参数通过一个参数名和值来指定,用"="隔开。
内存hash数据库支持"bnum", "capnum", 和 "capsiz"
内存tree数据库支持"capnum" 和 "capsiz"
capnum指定记录的最大容量,capsiz指定最大的内存使用量(在内存数据库中),记录通过存储的顺序移除。
hash数据库支持"mode", "bnum", "apow", "fpow", "opts", "rcnum", 和 "xmsiz".
`rcnum'指定最大的缓存记录数。如果它不大于零,那么缓存记录不可用。默认不可用。
xmsiz 指定外部内存的大小。如果不大于0,内存不可用。默认是67108864,即64M。
`bnum' 指定bucket存储桶的数量。如果指定的数目不大于0,将会使用默认的数值131071.推荐数量应该在所有需要存储的记录总数的0.4-4倍
`apow' 跟一个key关联的记录数,2的N次方表示. 如果不指定,默认2^4=16.
`fpow' specifies the maximum number of elements of the free block pool by power of 2. 默认2^10=1024.
`opts' 指定选项,位或:`HDBTLARGE' 指定数据库的大小通过使用64位数组桶能够超过2G。
`HDBTDEFLATE' 指定每个记录被Deflate encoding压缩。
`HDBTBZIP' 指定每个记录被BZIP2 encoding压缩
`HDBTTCBS'指定每个记录被 TCBS encoding压缩.
B+ tree数据库支持"mode", "lmemb", "nmemb", "bnum", "apow", "fpow", "opts", "lcnum", "ncnum", 和 "xmsiz".
Fixed-length 数据库 支持 "mode", "width", and "limsiz".
Table 数据库支持 "mode", "bnum", "apow", "fpow", "opts", "rcnum", "lcnum", "ncnum", "xmsiz", 和 "idx"
"idx"指定表的索引。
"mode"可以包含 "w" 写, "r" 读, "c" 创建, "t" 截断,"e" 无锁,和"f" 非阻塞锁。默认的的mod为"wc"。
优化性能
如果使用hash数据库我们可以指定#bnum=xxx来提高性能。xxx大于或等我我们的记录总数。
如果使用B+ tree数据库我们可以通过指定"#lcnum=xxx#bnum=yyy" 来提高性能.第一个参数指定被缓存的最大叶子节点数,受内存容量限制,第二个参数指定桶的数量,它应该大于总记录数的1/128.
如果有大量的客户端连接,确保我们的文件描述符够用。系统默认是1024,我们可以用使用“ulimit”来重新设定
比如下面的单机实例启动脚本(一个正在线上运行的脚本):
#!/bin/sh
ulimit -SHn 51200
ttserver -host 192.168.0.136 -port 11212 -thnum 8 -dmn -pid /data/ttserver/ttserver.pid -log /data/ttserver/ttserver.log -le -ulog /data/ttserver/ -ulim 128m -sid 1 -rts /data/ttserver/ttserver.rts /data/ttserver/database.tch#bnum=10000000#xmsiz=434217728#rcnum=20000
使用hash数据库,最大会缓存20000个记录,最大使用内存434217728bytes(414M),bucket存储桶的数量10000000。
目前的库大小:
-rw-r--r-- 1 root root 28G Mar 8 12:19 bbsdatabase.tch
因为使用了64位操作系统,所以文件大小不受2G的限制。
我们再看下读取数据的速度:
当前获取memcache Threads_cdb_threads_tid3565732_displayorder_0 使用时间 0.00054812431335449
以上是程序打印出来的通过memcache协议读取key为memcache Threads_cdb_threads_tid3565732_displayorder_0的数据所花的时间0.00054812431335449(s),可以看到速度还是非常快的。
启动实例
个人推荐通过修改ttservctl来实现启动。下面我们举几个简单的启动例子。
单机启动例子,下面是ttservctl文件的部分:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/var/ttserver" #数据库存放的路径,比如改为"/data/mydata"
port="1978" #启动的端口
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/ulog"
ulimsiz="256m"
sid=1
dbname="$basedir/casket.tch#bnum=1000000" #上面讲的数据库类型配置
maxcon="65536"
retval=0
双机互为主辅模式,比如两台机器的Ip分别为192.168.1.176和192.168.1.1.177,以下为ttservctl文件的一部分。
176的配置:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/data/data/data1"
port="11211"
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/"
mhost="192.168.1.177" #主ip即另外机器的ip
ulimsiz="256m"
sid=6#注意要每台机器不一样
dbname="$basedir/casket.tch#bnum=100000000#xmsiz=104857600#rcnum=1000000"
rts="$basedir/ttserver.rts" #在ttservctl基础上增加
maxcon="65536"
retval=0
# locale clear
LANG=C
LC_ALL=C
export LANG LC_ALL
# start the server
start(){
printf 'Starting the server of Tokyo Tyrant\n'
ulimit -n "$maxcon"
mkdir -p "$basedir"
if [ -f "$pidfile" ] ; then
pid=`cat "$pidfile"`
printf 'Existing process: %d\n' "$pid"
retval=1
else
$cmd \
-port "$port" \
-dmn \
-pid "$pidfile" \
-log "$logfile" \
-ulog "$ulogdir" \
-ulim "$ulimsiz" \
-sid "$sid" \
-mhost "$mhost" \#在ttservctl基础上增加
-mport "$port" \#在ttservctl基础上增加
-rts "$rts" \#在ttservctl基础上增加
"$dbname"
if [ "$?" -eq 0 ] ; then
printf 'Done\n'
else
printf 'The server could not started\n'
retval=1
fi
fi
}
177的配置:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/data/data/data1"
port="11211"
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/"
mhost="192.168.1.176" #主ip即另外机器的ip
ulimsiz="256m"
sid=7#注意要每台机器不一样
dbname="$basedir/casket.tch#bnum=100000000#xmsiz=104857600#rcnum=1000000"
rts="$basedir/ttserver.rts" #在ttservctl基础上增加
maxcon="65536"
retval=0
# locale clear
LANG=C
LC_ALL=C
export LANG LC_ALL
# start the server
start(){
printf 'Starting the server of Tokyo Tyrant\n'
ulimit -n "$maxcon"
mkdir -p "$basedir"
if [ -f "$pidfile" ] ; then
pid=`cat "$pidfile"`
printf 'Existing process: %d\n' "$pid"
retval=1
else
$cmd \
-port "$port" \
-dmn \
-pid "$pidfile" \
-log "$logfile" \
-ulog "$ulogdir" \
-ulim "$ulimsiz" \
-sid "$sid" \
-mhost "$mhost" \#在ttservctl基础上增加
-mport "$port" \#在ttservctl基础上增加
-rts "$rts" \#在ttservctl基础上增加
"$dbname"
if [ "$?" -eq 0 ] ; then
printf 'Done\n'
else
printf 'The server could not started\n'
retval=1
fi
fi
}
Tokyo Tyrant(TTServer)系列-memcache协议
通过memcache协议使用ttserver
通过telnet 127.0.0.1 1978 telnet连接到到我们第一节的启动实例。
以下我们通过add增加key为key1和value为value1的数据。
通过get key1获取数据,如果你看不明白,可以搜索下memcache协议的东西看下。
add key1 1 0 6
value1
STORED
get key1
VALUE key1 0 6
value1
END
通过php使用
$mem=new Memcache();
$mem->connect("192.168.15.178",1978);
$mem->add("key2","value2");
print_r( $mem->get("key2"));
echo "<hr>";
$mem->add("key3",array("value3"=>"this is value3"));
print_r($mem->get("key3"));
?>
运行后输出:
value2
________________________________________
a:1:{s:6:"value3";s:14:"this is value3";}
需要注意的问题
序列化问题
如果你熟悉memcache协议,或者你曾经用php的memcache来使用ttserver,你可能马上就发现了上面的问题。
比如我们key3是一个数组,但是我们取回来的是一个序列化的字符串,没有自动反序列化,在memcached服务器上是会自动反序列化的。
通过上面的telnet示例我们可以看到,我们add key1的时候设置flag参数为1,但是我们get回来的时候,返回的flag参数是0,实际上,ttserver是没有存储flag参数的,统一的都 使用0,这就造成了php使用时不会自动反序列化,当然,如果你使用压缩参数,一样会有这样的问题。
怎么样解决这个问题,如果要修改ttserver的代码实为不方便。我们完全可以在php,或者我们的客户端来控制。
比如value我们统一的都序列化后存储,取出来的时候我们再反序列化。
自增问题
//使用ttserver自增
$mem=new Memcache();
$mem->connect("192.168.15.178",1978);
var_dump($mem->increment("incr"));
//结果为int(1)
?>
//使用memcache自增
$mem=new Memcache();
$mem->connect("192.168.15.178",11211);
var_dump($mem->increment("incr"));
//结果为bool(false)
?>
我们看到同样的代码用在memcache返回了失败(false).我们可以在php手册上看到这样一句话“Memcache::increment() does not create an item if it didn't exist.”但是同样的,用在ttserver上就是成功的。这一点要特别注意。
Tokyo Tyrant(TTServer)系列-高可用性和高可靠性+nginx
1.基于memcache协议的高可用性
1.1构建一个互为主辅的ttserver.
图中构建了在ip为177和178两台机器的互为主辅结构的ttserver.
1.2在php中实现高可用
非常幸运,php的memcache客户端直接就可以实现故障转移的功能。其中的addServer函数或者方法非常好。
bool Memcache::addServer ( string $host [, int $port [, bool $persistent [, int $weight [, int $timeout [, int $retry_interval [, bool $status [, callback$failure_callback [, int $timeoutms ]]]]]]]] )
$memcache = new Memcache;
$memcache->addServer('192.168.0.177', 11211);
$memcache->addServer('192.168.0.178', 11211);
$memcache->get("key");
?>
addServer 会把其中加入的ip放到一个池中,然后使用对键hash的方式(默认是crc32(key) % current_server_num)进行存取选择服务器,当其中一台服务器宕机不可用时,current_server_num就会减一,进行重新hash连接新的服务器,这样就实现了故障的自动转移。具体其中的原理可以查看php手册中关于memcache部分。
1.3其他语言
http://code.google.com/p/memcached/wiki/Clients这是一个memcached的client API的各种语言实现的列表,几乎所有的api都有提供php类似的addServer实现故障转移功能。
2.利用nginx实现http协议的高可用性
2.1为什么要把nginx扯进来?
ttserver提供了http接口
ttserver没有提供安全保证
nginx在处理http请求和反向代理的性能非常好
nginx的反向代理具有负载均衡和健康检查功能
2.2如何结合nginx实现高可用性
2.2.1配置
在nginx配置文件中增加:
upstream backend {
server 192.168.0.177:11211 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.2.178:11211 weight=1 max_fails=3 fail_timeout=30s;
}
利用upstream指向后端的两台机器。
location ~* /count(.*) {
if ($request_method = PUT ) {
return 403;
}
if ($request_method = DELETE ) {
return 403;
}
if ($request_method = POST ) {
return 403;
}
proxy_method GET;
proxy_pass http://backend;
}
当路径包含/count的时候,则代理到ttserver后端进行请求数据。请注意,这里屏蔽了PUT,DELETE,POST方法,只是使用了GET,主要目的是为了安全性,因为DELETE,POST,PUT是可以修改数据的。
2.2.2使用
使用以上的配置文件,启动nginx就可以访问ttserver中的内容了。比如访问http://host/count_key1将会显示ttserver中key为”count_key1”的内容。当我们不同时停掉177和178时,前端通过nginx http://host/count_key1都是同样可以可用的。
Tokyo Tyrant(TTServer)系列-备份恢复和增加从库
前面我们说了TTServer 的使用,以及如何在开始的时候配置主从。在使用中它非常高效和可靠,那么如果我们的服务运行一段时间后,需要增加一个从库(ttserver)来分担压力 或者用于负载均衡和HA,因为是线上系统,那么就不应该停机,那么我们应该怎么对数据进行备份和拷贝,然后启动一个slave从库呢?
1.如何备份和恢复
登录到ttserver服务器,执行如下命令
# tcrmgr copy -port 11211 localhost /data/backup.tch
localhost :ttserver主机名
/data/backup.tch 备份文件保存的路径,请注意,这里指ttserver所在机器的路径。
同样,也可以备份远程机器,
# tcrmgr copy -port 11211 remotehost /data/backup.tch
备份文件将保存在remotehost的/data/backup.tch
接下来恢复数据就比较简单,直接替换掉原有ttserver的数据文件,启动就可以了。
这种方式适用于定期的数据备份,在出现灾难故障时可以恢复到某一个时间的数据。不适合用来增加从库时需要的数据库文件。
2.如何不停机增加从库
从库需要进行同步,那么就需要有个文件的时间版本,防止数据冲突。
首先我们建立一个一个如下的脚本文件,存为"backup.sh",并赋予执行权限(chmod 755 backup.sh)。比如存在:/data/backup/路径下。
#! /bin/sh
srcpath="$1"
destpath="$1.$2"
rm -f "$destpath"
cp -f "$srcpath" "$destpath"
接下执行如下命令,执行的时间会根据你的磁盘性能和数据大小而定。
tcrmgr copy -port 11211 masterhost '@/data/backup/backup.sh'
materthost:主库主机名,请注意:backup.sh存放的路径是在materthost机器上。
'@/data/backup/backup.sh' :如果tcrmgr copy命令中,参数以@开始,那么后面的字符串作为命令行执行。
执行完成后,我们进入ttserver的数据目录,执行ls -lh会发现类似下面的文件名,
-rw-r--r-- 1 root root 9.2G Aug 25 14:31 casket.tch.1251181588942889
请确认产生casket.tch.xxxxx类似的文件名,xxxxx代表时间戳。
接下来在从库salve上以我们备份的文件来运行ttserver,把时间错写入到一个时间戳文件ttserver.rts。
$ ls
$ cp casket.tch.xxxxx casket.tch
$ echo xxxxx >ttserver.rts
$ mkdir ulog
$ ttserver -mhost masterhost -mport mport -port 11211 -ulog ulog -sid 2 -rts ttserver.rts casket.tch
运行后,ttserver将会以此时间戳进行同步。
masterhost :主库主机名
mport : 主库端口号
到此我们就完成了一个salve从库ttserver的增加。
3.小结
推荐备份也使用2中用到的方式,上面带上了时间戳,可以精确的知道数据的版本时间。
另外请注意:在使用此方法进行备份的时候,ttserver会在备份过程中一直保持同步阻塞和不修改数据。所以可以保证备份出来的版本跟时间戳的一致性。
Tokyo Tyrant(TTServer)系列-数据压缩
由于忙于工作,好久继续写关于ttserver的东西了。最近由于服务器准备的原因,只能在32位上做ttserver的测试,很快数据就达到 2G,ttserver无法正常工作,于是想到了ttserver的压缩功能,发现压缩比例挺大。所以进行了一些测试并在项目中做了一些应用。本文将展示 在64下面进行压缩的压缩比以及进行压缩的好处。
压缩测试
数据:2720268条原始新闻数据,每条数据使用json格式进行存储。
A机器ttserver配置:casket.tch#bnum=100000000#xmsiz=524288000#rcnum=200000#opts=ld
B机器ttserver配置:casket.tch#bnum=100000000#xmsiz=524288000#rcnum=200000
分别把原始新闻数据存储A机器和B机器。其中A和B的ulog日志文件大小都为19G。接下来来看ttserver的数据库文件大小,
A机器(有压缩)6.1G,B机器 (无压缩)17G。压缩后大概只占原来文件的1/3。
配置中的#opts=ld的d表示使用压缩。关于opts可以参考官方的原话:
"opts" can contains "l" of large option, "d" of Deflate option, "b" of BZIP2 option, and "t" of TCBS option.
经过初步测试,d是速度比较快的一种了。
压缩的优点
存储空间,压缩首先给人带来的优点肯定就是节约存储空间,这点在服务器空间不足的情况下使用非常有用,当然,你在32位2G文件大小的限制下,使用压缩的话就可以存储更多的数据。
IO性能:经过压缩,数据本身变得小了,对磁盘的IO也会相应减小,如果你的磁盘IO对你的应用形成了瓶颈,那么压缩也是可以为你来带益处的。对于IO的性能提高在硬盘结构和工作方式上也能得到解释。
压缩的缺点
使用压缩肯定就会耗费CPU资源了,所以CPU和空间只是一个权衡,根据经验,一般来说使用压缩都是没有问题的。比如nginx的gzip压缩静态文件(js,css)。
ttserver的压缩跟memcached的压缩的比较
提交到了比较,肯定就有不一样的地方。ttserver使用了内部压缩,就是服务器端(ttserver)负责压缩。而memcached的压缩则是客户端进行的,memcached只是负责存储压缩后的数据。客户端client根据flag参数来确定是否解压。ttserver是服务器负责压缩,memcache是客户端负责压缩。
ttserver输出的是解压后的数据,memcached输出的就是输入的压缩数据(数据使用压缩的情况)。这样就形成一个区别,memcached使用压缩后,由于输出的是压缩数据,会降低网络传输,而ttserver则不会有任何改变。
关于memcached的使用请网上搜索相应的介绍。
请注意Tokyo Tyrant (ttserver)在大数据量下的不稳定
ttserver不稳定案例
1. CMS a系统的文章采用了ttserver存储。在数据达到30多G的时候,经常出现写入失败,还出现了几次意外崩溃,无法重启成功,只得从slave恢复数据。
2.CMS b系统的图片使用ttserver存储,在数据导到65G的时候出现无法写入的情况,重启后问题依旧,只得从slave重新恢复数据重启。
3.BBS系统采用ttserver做缓存,设计上采用如果没有更新,那么缓存永久存在的策略。在数据达到65GB,数据条数在700多万条的时 候,出现大量写入失败的情况,系统负载开始上升,日志出现大量do_mc_set: operation failed。当然这里作为缓存比较好处理,删掉,重新建个新的就OK。(注:启动参数 data.tch#bnum=10000000#xmsiz=434217728#rcnum=20000)
测试中ttserver写入表现不稳定
1.#bum=10000000
插入940多万数据(一条7.2k)时出现崩溃(测了两次都一样,看起来好像内部出现了死锁,连上后,无法进行任何响应,没有任何操作时,也占了大量CPU)。越到后面插入的qps(每秒响应数)越小。而且波动比较大。
#bum=100000000
可以顺利插入上千万的数据,但是越到后面qps越小。越到后面插入的qps(每秒响应数)越小。而且波动比较大。
2.跟其他的nosql(mongodb,bdb je,cassandra)对比测试,在写入上,ttserver是表现最不稳定的,其他的nosql都非常好。
总结和注意
1.经过对Tokyo Cabinet 的测试,同样跟ttserver一样,所以应该是Tokyo Cabinet 导致的不稳定。在选择btree方式存储时,随着数据量的增加一样不稳定。在优化参数上也做了各种尝试。
2.ttserver在性能的表现上非常不俗,特别是内存占用和cpu占用都很低,能同时响应上万的并发。但是你应该注意,他一般在数据导到20G以上就会出现不稳定情况。
所以用ttserver来存储单条比较小的数据非常好,存储大文本或者大的二进制文件,由于空间占用上升很快,很快就会变得不稳定。
3.注意备份,使用master-slave是个非常好的主意,在ttserver崩溃导致文件损坏或者其他什么原因无法启动时,你可以从slave 拷贝数据文件来进行恢复。
4.如果你一定要使用ttserver,建议对数据进行分片(sharding)存储,或者你自己使用一个网络接口,底层使用Tokyo Cabinet 来进行分片存储。
5.以上只是个人在使用中遇到的情况,本人正在尝试在存储大文本的ttserver进行替换掉。
Tokyo Tyrant (ttserver)的master-slave复制协议分析
The replication protocol of Tokyo Tyrant (ttserver)
[文章作者:孙立 链接:http://www.cnblogs.com/sunli/ 更新时间:2010-06-26]
目的
ttserver已经自带了主从复制功能,而且运行非常稳定,高效,使我们在使用ttserver实现高可靠性的不二选择。为什么我还要分析它的复制协议呢?
1.需要实时从ttserver同步数据到一个异构库。比如mysql,其他的nosql数据库。
2.数据的无缝迁移,如果需要从ttserver数据库无缝切换到其他数据库,可以使用这种复制协议
3.高性能的异步处理队列,你可以设置主库为mem类型,然后使用同步协议获取数据,这实际上就是一个队列,而且还是一个持久化的队列服务。
4.其他存储写一个服务,可以用ttserver做slave。
协议结构分析
咱们从数据流向的流程开始:
1. 客户端(slave)连接到服务器端(master)
2. slave连接成功后向master发送
+--------------------------------------+
|0xC8 |0xa0 | slave rts | slave sid |
|1byte |1 byte | 8 bytes | 4 bytes |
+--------------------------------------+
3. master收到后,想客户端发送:
+---------+
|mid |
|4 bytes |
+---------+
4. slave收到后可以得到服务器端的master sid.
5. 这里就开始复制了,master继续想客户端循环不断的发送复制的数据的object.
+------+
|0xca | 表示没有任何操作
|1 byte|
+------+
发送一个操作项:
+--------------------------------------------------+
|0xc9 |rts | rsid |rsize |data |
|1 byte |8 bytes |4 bytes |4 bytes |rsize bytes |
+--------------------------------------------------+
其中data的结构:
+-----------------------------------+
|magic |cmd |[data] |
|1 bytes |1 bytes | key-value data |
+-----------------------------------+
cmd表示各种操作类型,比如put putkeep 等
6. slave循环接受数据进行数据ok了。
协议实现
ttserver的复制协议非常简单,因为官方并没有把复制协议写到文档中,其他操作都有文档的。就需要去分析它的C代码,结构分析出来实现就非常简单了。 我会开放一些实现,到时会在www.cnblogs.com/sunli/公布
Tokyo(ttserver)使用手册摘要
1 概述
Tokyo是Tokyo Cabinet和Tokyo Tyrant的简称,合在一起用也称ttserver。
Tokyo Cabinet 是日本人 平林幹雄 开发的一款 NoSQL 数据库,数据库由一系列key-value对的记录构成,类似bdb。
Tokyo Tyrant 是由同一作者开发的 Tokyo Cabinet 数据库网络接口。它拥有Memcached兼容协议,也可以通过HTTP协议进行数据交换。Tokyo Tyrant 加上 Tokyo Cabinet,构成了一款支持高并发的分布式持久存储系统Tokyo。
对Tokyo内部机制感兴趣的请参考陈海涛 chenht@ucweb.com:《Tokyo代码剖析》;
针对使用tt时出现太多误用,参数误设或未设,提供使用手册的摘要。在此开一个讨论的头。
2 Tokyo的安装
测试了在32位机器和64位机器都运行正常,64位机器可以支持>2G的单个db文件;
32位机器加上编译选项” --enable-off64”后也能支持>2G的单个db文件,但是不能突破32位Linux 3G用户内存空间的限制,所以内存最大只能用3G的,除非安装64位操作系统。
可用普通用户安装和运行。
Tokyo Cabinet依赖下面的库,一般Linux会自带,编译出错的话则需先安装:
zlib : 用来压缩. 1.2.3版本或更新的.
bzip2 : 用来压缩. 1.0.5版本或更新的.
下面的例子都是基于$HOME/local目录,使用时可更改。
下载最新的包(注意别下载到旧包了),2010年8月推荐用的最新版本是:
http://1978th.net/tokyotyrant/Latest Source Package (version 1.1.41)
http://1978th.net/tokyocabinet/Latest Source Package (version 1.4.46)
注:新版本主要进行bugfix,请尽量下载最新版本,changelog在源代码包里面。
下载后传到Linux的目录解压:
tar zxvf ***.tar.gz
2.1 Tokyocabinet
cd tokyocabinet-***
32位操作系统:
./configure --prefix=$HOME/local/tokyocabinet/ --enable-off64
64位操作系统:
./configure --prefix=$HOME/local/tokyocabinet/
make
make install
2.1.1 32位操作系统支持大于2G的db文件
32位操作系统要支持大于2G的db文件请加上” --enable-off64”,否则会导致严重问题,db文件超过2G时表现为:
Tcrmgr inform显示记录数为0,实际数据并没有被清空;
连接暴多但都操作失败,ttserver.log内提示“ERROR ttacceptsock failed”和“ERROR do_mc_set: operation failed”等;
Ttserver检测到文件异常会悄悄退出。
2.2 Tokyotyrant
环境变量设置,cd $HOME 后vi .bash_profile,修改PATH和LD_LIBRARY_PATH加上Tokyo的相关安装路径:
PATH=$HOME/local/tokyocabinet/bin:$HOME/local/tokyotyrant/bin:$PATH
LD_LIBRARY_PATH=$HOME/local/tokyocabinet/lib:$HOME/local/tokyotyrant/lib:$LD_LIBRARY_PATH
export PATH
export LD_LIBRARY_PATH
然后安装:
./configure --prefix=$HOME/local/tokyotyrant \
--with-tc=$HOME/local/tokyocabinet
make
make install
安装后在$HOME/local目录下生成了安装目录:
cd $HOME/local/tokyotyran
mkdir log data
新建两个目录用来存放ulog和db文件等。
在两台主机都安装完后,于是可以执行下面的启动步骤了。
2.2.1 支持lua脚本
末尾加上–enable-lua表示支持lua脚本:
./configure --prefix=$HOME/local/tokyotyrant \
--with-tc=$HOME/local/tokyocabinet –enable-lua
2.3 版本查看
查看tc版本:
tcamgr --version
查看tt版本:
ttserver --version
3 Tokyo的启动
生产环境可用本例的目录结构,可将#后面的参数再调整。
3.1 Hash关键性能参数
Hash是B+tree的基础,数据put时直接写入文件或文件映射,并非写缓存,是比较安全的数据存储方式。数据量小时,全在缓存或内存映射内操作,读写很快。
而且写数据是单条写入,所以数据量超过内存映射xmsiz时后要直接写入db文件,性能下降明显,io升高明显。
"bnum", 用来保存计算完hash值后的每个key在db文件的位置,bnum太小时hash值冲突比例就大。冲突的key依次链接起来,查找时增加了搜寻次数;
该值持久化到db文件,全映射在内存,默认很小是131071,最大可以设几亿以上。,要减少hash冲突次数,则要设置bnum >= key个数,一般一年后key要达到5000万个,bnum则设置为5千万:50 000 000。
"opts", 指定压缩方式(hash的短数据压缩比不高)和bucket array对每条数据用4字节还是8字节保存文件偏移量,要支持db文件>2G请加“#opts=l”。要支持db文件>2G并且用效果较好的gzip用到的压缩算法请加“#opts=ld”。
hash方式单条数据很短(< 100字节)时压缩效果差,可以不用这个参数,否则请带上这个参数,但会占用更多cpu。
"rcnum", hash map缓存的记录数,get时放到这个缓存,set时从缓存清掉该key,默认0不缓存,设置则最小256,B+tree不用这个参数,缓存热点数据的,在get访问确定没明显热点时不要设置这个参数;在有明显热点时才需设置这个参数,在保证xmsiz足够大时这个参数推荐设小些,例如100万,因为会把rnum条key和value不加压缩地放内存,除非机器内存很充裕。
"xmsiz",指定文件映射尺寸,默认且最小为:256(放head等关键信息)+ bucket array的尺寸。注意这个最重要的参数必须>=db文件尺寸才能正常速度地响应,否则很慢,例如db文件最大会达到10G,则xmsiz设置为10G,单位字节。
上述参数中只有这个xmsiz参数在启动后还可通过重启调整。
3.2 B+tree关键性能参数
B+tree是基于hash机制实现的,复用上述的db文件格式和文件映射,不同的只是最上层缓存机制。
写入db数据时,是按叶节点或非页节点进行了打包分页,整页写入;压缩也是整页压缩,压缩比更高。写也进行了缓存。
但必须在备机上定期执行tcrmgr sync,否则异常重启丢掉数据。
"bnum", 同hash方式的,但bnum的数量大于或等于存储总记录数的1/128即可,因为b+tree是整页保存到hash db内。
"opts", 同hash方式的该选项,要支持db文件>2G请加“#opts=l”。要支持db文件>2G并且用效果较好的gzip压缩算法请加“#opts=ld”。
b+tree方式压缩是整页(128条记录)压缩,压缩效果很好,数据量大时用b+tree时带上压缩参数降低内存使用量效果明显,但会稍占用更多cpu。
"xmsiz",同hash方式的。
"lcnum", b+tree缓存叶节点数,每个叶节点上可放128条记录作为一页,减轻读写压力,缓存热点数据的,默认1024,设的话最小64,太大则stop和sync时耗时很多。在xmsiz足够大时这个参数别设置。
"ncnum", b+tree缓存非叶节点数,每个树节点上可放256条索引作为一页,索引指向叶节点,减轻读写压力, 缓存热点数据,默认512,设的话最小64,太大则stop和sync时耗时很多。通常为叶节点数的一半。
在xmsiz足够大时以上两个参数可不设置。
#define BDBDEFLCNUM 1024 // default number of leaf cache
#define BDBDEFNCNUM 512 // default number of node cache
3.3 Hash主-备启动命令
./ttserver -host 192.168.4.150 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 91 $HOME/local/tokyotyrant/data/database.tch#bnum=10000000#xmsiz=1024000000 #rcnum=1000000#opts=ld
./ttserver -host 192.168.4.151 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 92 -mhost 192.168.4.150 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tch#bnum=10000000#xmsiz=1024000000 #rcnum=1000000#opts=ld
3.4 B+tree主-主启动命令
./ttserver -host 192.168.4.150 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 91 -mhost 192.168.4.151 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tcb#bnum=10000000#xmsiz=2000000000 #lcnum=1024#ncnum=512#opts=ld
./ttserver -host 192.168.4.151 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 92 -mhost 192.168.4.150 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tcb#bnum=10000000#xmsiz=2000000000 #lcnum=1024#ncnum=512#opts=ld
Tokyo Cabinet 是日本人 Mikio Hirabayashi(平林幹雄)のページ 开发的一款DBM数据库(注:大名鼎鼎的DBM数据库qdbm就是他开发的),该数据库读写非常快。insert:0.4sec/1000000 recordes(2500000qps),写入100万数据只需要0.4秒。search:0.33sec/1000000 recordes (3000000 qps),读取100万数据只需要0.33秒。下图为各种key-value数据库读写数据的性能测试,可以看出Tokyo Cabinet的速度是非常快的。
Tokyo Tyrant 提 供dbm数据库Tokyo Cabinet的网络接口。它使用简单的基于TCP/IP的简单二进制协议进行通信。同时它拥有Memcached兼容协议并且可以用HTTP/1.1协 议进行数据交换。所以实现了跨平台,跨语言使用Tokyo Tyrant。采用热备份,更新日志记录,复制(replication)来实现高可用性和高可靠性。到目前为止,Tokyo Tyrant只能运行在inux, FreeBSD, Mac OS X, Solaris。
下面我们介绍如何安装Tokyo Tyrant。
首先我们安装Tokyo Cabinet.
#wget http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.9.tar.gz
#tar -xzvf tokyocabinet-1.4.9.tar.gz
# cd tokyocabinet-1.4.9
# ./configure
# make
# make install
OK,我们装好了Tokyo Cabinet,再继续安装Tokyo Tyrant。
# wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.16.tar.gz
# tar -xzvf tokyotyrant-1.1.16.tar.gz
#cd tokyotyrant-1.1.16
# ./configure
# make
#make install
OK,我们目前就完成了Tokyo Tyrant的安装。安装非常的简单。安装好的Tokyo Tyrant的启动程序文件叫ttserver,所以我们也简称ttserver.下面我们简单启动一个数据库,测试我们是否安装成功。
# ./ttservctl start
启动完成。这是自带的一个启动脚本,你可以拷贝到到任意目录,修改里面的参数。
# telnet 127.0.0.1 1978
然后我们telnet到1978端口,因为刚才的脚本默认启动的数据库使用了1978端口。
如果顺利,你可以看到可以连通,键入stats然后回车,可以看到一些类似如下的状态信息
stats
STAT pid 24755
STAT uptime 37
STAT time 1236396011
STAT version 1.1.16
STAT rusage_user 0.000000
STAT rusage_system 0.008998
STAT curr_items 0
STAT bytes 4198720
END
请注意:在32位操作系统下,Tokyo Cabinet的单个数据库文件不能超过2G,而在64位操作系统下则没有这一限制。所以推荐使用64位操作系统和CPU。
Tokyo Tyrant(TTServer)系列-启动参数和配置
启动参数介绍
ttserver命令可以启动一个数据库实例。因为数据库已经实现了Tokyo Cabinet的抽象API,所以可以在启动的时候指定数据库的配置类型。
支持的数据库类型有:
1、内存hash数据库
2、内存tree数据库
3、hash数据库
4、B+ tree数据库
命令通过下面的格式来使用,‘dbname’制定数据库名,如果省略,则被视作内存hash数据库。
ttserver [-host name] [-port num] [-thnum num] [-tout num] [-dmn] [-pid path] [-log path] [-ld|-le] [-ulog path] [-ulim num] [-uas] [-sidnum] [-mhost name] [-mport num] [-rts path] [-ext path] [-extpc name period] [-mask expr] [dbname]
下面来说这些参数的功能:
• -host name :指明服务器的hostname或者ip地址。默认服务器的所有地址都会被绑定。比如:指定127.0.0.1这样的ip,就只是本地可以访问了。
• -port num : 指定服务启动的端口. 默认1978.如果要启动多个数据库实例,端口需要不一样。
• -thnum num : 指定服务工作的线程数。默认8.
• -tout num : 指定每个会话的超时时间。默认永不超时。
• -dmn : 以守护进程方式运行。
• -pid path : 输出进程IP到指定的文件。
• -log path : 输出日志信息到指定文件。
• -ld : 日志中记录debug信息。
• -le :日志中只记录错误信息。
• -ulog path : 指定存放更新日志(update log)的目录.可以用来备份恢复数据库,主从库之间的同步。
• -ulim num : 指定每个更新日志文件的大小限制.
• -uas :使用异步IO记录更新日志。(使用此项可以减少写入日志的IO开销,但是在服务器意外关机,进程被kill时可能会丢失数据。根据经验,一般可以不使用)。
• -sid num : 指定服务的ID号。主从复制的时候通过不同的ID号来识别。
• -mhost name : 指定主从复制模式下的主服务器的IP或域名。
• -mport num : 指定主从模式下主服务器的端口号.
• -rts path : 指定用于主从复制的时间戳存放文件.
• -ext path : 指定扩展脚本语言文件。
• -extpc name period : 指定被周期调用的函数名和间隔时间.
• -mask expr : 指定被禁止的命令名(比如可以禁止使用清空vanish).
• -unmask expr : 指定被允许的命令名.
数据库类型
下面我们再来看下数据库类型的详细配置。
1、 数据库名的命名方式被Tokyo Cabinet的抽象API指定。
2、 如果数据库名为"*",表示内存hash数据库。
3、 如果数据库名为"+"表示内存tree数据库。
4、 如果数据库名为".tch",则数据库为hash数据库。
5、 如果数据库名的后缀为".tcb",数据库将为B+ tree数据库。
6、 如果数据库名的后缀为".tcf"。则数据库将为fixed-length数据库。
7、 如果数据库名的后缀为".tct",则数据将为一个table数据库(有表的概念)。
数据库的调整参数通过数据库名的延伸来指定,通过"#"分开,每个参数通过一个参数名和值来指定,用"="隔开。
内存hash数据库支持"bnum", "capnum", 和 "capsiz"
内存tree数据库支持"capnum" 和 "capsiz"
capnum指定记录的最大容量,capsiz指定最大的内存使用量(在内存数据库中),记录通过存储的顺序移除。
hash数据库支持"mode", "bnum", "apow", "fpow", "opts", "rcnum", 和 "xmsiz".
`rcnum'指定最大的缓存记录数。如果它不大于零,那么缓存记录不可用。默认不可用。
xmsiz 指定外部内存的大小。如果不大于0,内存不可用。默认是67108864,即64M。
`bnum' 指定bucket存储桶的数量。如果指定的数目不大于0,将会使用默认的数值131071.推荐数量应该在所有需要存储的记录总数的0.4-4倍
`apow' 跟一个key关联的记录数,2的N次方表示. 如果不指定,默认2^4=16.
`fpow' specifies the maximum number of elements of the free block pool by power of 2. 默认2^10=1024.
`opts' 指定选项,位或:`HDBTLARGE' 指定数据库的大小通过使用64位数组桶能够超过2G。
`HDBTDEFLATE' 指定每个记录被Deflate encoding压缩。
`HDBTBZIP' 指定每个记录被BZIP2 encoding压缩
`HDBTTCBS'指定每个记录被 TCBS encoding压缩.
B+ tree数据库支持"mode", "lmemb", "nmemb", "bnum", "apow", "fpow", "opts", "lcnum", "ncnum", 和 "xmsiz".
Fixed-length 数据库 支持 "mode", "width", and "limsiz".
Table 数据库支持 "mode", "bnum", "apow", "fpow", "opts", "rcnum", "lcnum", "ncnum", "xmsiz", 和 "idx"
"idx"指定表的索引。
"mode"可以包含 "w" 写, "r" 读, "c" 创建, "t" 截断,"e" 无锁,和"f" 非阻塞锁。默认的的mod为"wc"。
优化性能
如果使用hash数据库我们可以指定#bnum=xxx来提高性能。xxx大于或等我我们的记录总数。
如果使用B+ tree数据库我们可以通过指定"#lcnum=xxx#bnum=yyy" 来提高性能.第一个参数指定被缓存的最大叶子节点数,受内存容量限制,第二个参数指定桶的数量,它应该大于总记录数的1/128.
如果有大量的客户端连接,确保我们的文件描述符够用。系统默认是1024,我们可以用使用“ulimit”来重新设定
比如下面的单机实例启动脚本(一个正在线上运行的脚本):
#!/bin/sh
ulimit -SHn 51200
ttserver -host 192.168.0.136 -port 11212 -thnum 8 -dmn -pid /data/ttserver/ttserver.pid -log /data/ttserver/ttserver.log -le -ulog /data/ttserver/ -ulim 128m -sid 1 -rts /data/ttserver/ttserver.rts /data/ttserver/database.tch#bnum=10000000#xmsiz=434217728#rcnum=20000
使用hash数据库,最大会缓存20000个记录,最大使用内存434217728bytes(414M),bucket存储桶的数量10000000。
目前的库大小:
-rw-r--r-- 1 root root 28G Mar 8 12:19 bbsdatabase.tch
因为使用了64位操作系统,所以文件大小不受2G的限制。
我们再看下读取数据的速度:
当前获取memcache Threads_cdb_threads_tid3565732_displayorder_0 使用时间 0.00054812431335449
以上是程序打印出来的通过memcache协议读取key为memcache Threads_cdb_threads_tid3565732_displayorder_0的数据所花的时间0.00054812431335449(s),可以看到速度还是非常快的。
启动实例
个人推荐通过修改ttservctl来实现启动。下面我们举几个简单的启动例子。
单机启动例子,下面是ttservctl文件的部分:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/var/ttserver" #数据库存放的路径,比如改为"/data/mydata"
port="1978" #启动的端口
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/ulog"
ulimsiz="256m"
sid=1
dbname="$basedir/casket.tch#bnum=1000000" #上面讲的数据库类型配置
maxcon="65536"
retval=0
双机互为主辅模式,比如两台机器的Ip分别为192.168.1.176和192.168.1.1.177,以下为ttservctl文件的一部分。
176的配置:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/data/data/data1"
port="11211"
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/"
mhost="192.168.1.177" #主ip即另外机器的ip
ulimsiz="256m"
sid=6#注意要每台机器不一样
dbname="$basedir/casket.tch#bnum=100000000#xmsiz=104857600#rcnum=1000000"
rts="$basedir/ttserver.rts" #在ttservctl基础上增加
maxcon="65536"
retval=0
# locale clear
LANG=C
LC_ALL=C
export LANG LC_ALL
# start the server
start(){
printf 'Starting the server of Tokyo Tyrant\n'
ulimit -n "$maxcon"
mkdir -p "$basedir"
if [ -f "$pidfile" ] ; then
pid=`cat "$pidfile"`
printf 'Existing process: %d\n' "$pid"
retval=1
else
$cmd \
-port "$port" \
-dmn \
-pid "$pidfile" \
-log "$logfile" \
-ulog "$ulogdir" \
-ulim "$ulimsiz" \
-sid "$sid" \
-mhost "$mhost" \#在ttservctl基础上增加
-mport "$port" \#在ttservctl基础上增加
-rts "$rts" \#在ttservctl基础上增加
"$dbname"
if [ "$?" -eq 0 ] ; then
printf 'Done\n'
else
printf 'The server could not started\n'
retval=1
fi
fi
}
177的配置:
#! /bin/sh
#----------------------------------------------------------------
# Startup script for the server of Tokyo Tyrant
#----------------------------------------------------------------
# configuration variables
prog="ttservctl"
cmd="ttserver"
basedir="/data/data/data1"
port="11211"
pidfile="$basedir/pid"
logfile="$basedir/log"
ulogdir="$basedir/"
mhost="192.168.1.176" #主ip即另外机器的ip
ulimsiz="256m"
sid=7#注意要每台机器不一样
dbname="$basedir/casket.tch#bnum=100000000#xmsiz=104857600#rcnum=1000000"
rts="$basedir/ttserver.rts" #在ttservctl基础上增加
maxcon="65536"
retval=0
# locale clear
LANG=C
LC_ALL=C
export LANG LC_ALL
# start the server
start(){
printf 'Starting the server of Tokyo Tyrant\n'
ulimit -n "$maxcon"
mkdir -p "$basedir"
if [ -f "$pidfile" ] ; then
pid=`cat "$pidfile"`
printf 'Existing process: %d\n' "$pid"
retval=1
else
$cmd \
-port "$port" \
-dmn \
-pid "$pidfile" \
-log "$logfile" \
-ulog "$ulogdir" \
-ulim "$ulimsiz" \
-sid "$sid" \
-mhost "$mhost" \#在ttservctl基础上增加
-mport "$port" \#在ttservctl基础上增加
-rts "$rts" \#在ttservctl基础上增加
"$dbname"
if [ "$?" -eq 0 ] ; then
printf 'Done\n'
else
printf 'The server could not started\n'
retval=1
fi
fi
}
Tokyo Tyrant(TTServer)系列-memcache协议
通过memcache协议使用ttserver
通过telnet 127.0.0.1 1978 telnet连接到到我们第一节的启动实例。
以下我们通过add增加key为key1和value为value1的数据。
通过get key1获取数据,如果你看不明白,可以搜索下memcache协议的东西看下。
add key1 1 0 6
value1
STORED
get key1
VALUE key1 0 6
value1
END
通过php使用
$mem=new Memcache();
$mem->connect("192.168.15.178",1978);
$mem->add("key2","value2");
print_r( $mem->get("key2"));
echo "<hr>";
$mem->add("key3",array("value3"=>"this is value3"));
print_r($mem->get("key3"));
?>
运行后输出:
value2
________________________________________
a:1:{s:6:"value3";s:14:"this is value3";}
需要注意的问题
序列化问题
如果你熟悉memcache协议,或者你曾经用php的memcache来使用ttserver,你可能马上就发现了上面的问题。
比如我们key3是一个数组,但是我们取回来的是一个序列化的字符串,没有自动反序列化,在memcached服务器上是会自动反序列化的。
通过上面的telnet示例我们可以看到,我们add key1的时候设置flag参数为1,但是我们get回来的时候,返回的flag参数是0,实际上,ttserver是没有存储flag参数的,统一的都 使用0,这就造成了php使用时不会自动反序列化,当然,如果你使用压缩参数,一样会有这样的问题。
怎么样解决这个问题,如果要修改ttserver的代码实为不方便。我们完全可以在php,或者我们的客户端来控制。
比如value我们统一的都序列化后存储,取出来的时候我们再反序列化。
自增问题
//使用ttserver自增
$mem=new Memcache();
$mem->connect("192.168.15.178",1978);
var_dump($mem->increment("incr"));
//结果为int(1)
?>
//使用memcache自增
$mem=new Memcache();
$mem->connect("192.168.15.178",11211);
var_dump($mem->increment("incr"));
//结果为bool(false)
?>
我们看到同样的代码用在memcache返回了失败(false).我们可以在php手册上看到这样一句话“Memcache::increment() does not create an item if it didn't exist.”但是同样的,用在ttserver上就是成功的。这一点要特别注意。
Tokyo Tyrant(TTServer)系列-高可用性和高可靠性+nginx
1.基于memcache协议的高可用性
1.1构建一个互为主辅的ttserver.
图中构建了在ip为177和178两台机器的互为主辅结构的ttserver.
1.2在php中实现高可用
非常幸运,php的memcache客户端直接就可以实现故障转移的功能。其中的addServer函数或者方法非常好。
bool Memcache::addServer ( string $host [, int $port [, bool $persistent [, int $weight [, int $timeout [, int $retry_interval [, bool $status [, callback$failure_callback [, int $timeoutms ]]]]]]]] )
$memcache = new Memcache;
$memcache->addServer('192.168.0.177', 11211);
$memcache->addServer('192.168.0.178', 11211);
$memcache->get("key");
?>
addServer 会把其中加入的ip放到一个池中,然后使用对键hash的方式(默认是crc32(key) % current_server_num)进行存取选择服务器,当其中一台服务器宕机不可用时,current_server_num就会减一,进行重新hash连接新的服务器,这样就实现了故障的自动转移。具体其中的原理可以查看php手册中关于memcache部分。
1.3其他语言
http://code.google.com/p/memcached/wiki/Clients这是一个memcached的client API的各种语言实现的列表,几乎所有的api都有提供php类似的addServer实现故障转移功能。
2.利用nginx实现http协议的高可用性
2.1为什么要把nginx扯进来?
ttserver提供了http接口
ttserver没有提供安全保证
nginx在处理http请求和反向代理的性能非常好
nginx的反向代理具有负载均衡和健康检查功能
2.2如何结合nginx实现高可用性
2.2.1配置
在nginx配置文件中增加:
upstream backend {
server 192.168.0.177:11211 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.2.178:11211 weight=1 max_fails=3 fail_timeout=30s;
}
利用upstream指向后端的两台机器。
location ~* /count(.*) {
if ($request_method = PUT ) {
return 403;
}
if ($request_method = DELETE ) {
return 403;
}
if ($request_method = POST ) {
return 403;
}
proxy_method GET;
proxy_pass http://backend;
}
当路径包含/count的时候,则代理到ttserver后端进行请求数据。请注意,这里屏蔽了PUT,DELETE,POST方法,只是使用了GET,主要目的是为了安全性,因为DELETE,POST,PUT是可以修改数据的。
2.2.2使用
使用以上的配置文件,启动nginx就可以访问ttserver中的内容了。比如访问http://host/count_key1将会显示ttserver中key为”count_key1”的内容。当我们不同时停掉177和178时,前端通过nginx http://host/count_key1都是同样可以可用的。
Tokyo Tyrant(TTServer)系列-备份恢复和增加从库
前面我们说了TTServer 的使用,以及如何在开始的时候配置主从。在使用中它非常高效和可靠,那么如果我们的服务运行一段时间后,需要增加一个从库(ttserver)来分担压力 或者用于负载均衡和HA,因为是线上系统,那么就不应该停机,那么我们应该怎么对数据进行备份和拷贝,然后启动一个slave从库呢?
1.如何备份和恢复
登录到ttserver服务器,执行如下命令
# tcrmgr copy -port 11211 localhost /data/backup.tch
localhost :ttserver主机名
/data/backup.tch 备份文件保存的路径,请注意,这里指ttserver所在机器的路径。
同样,也可以备份远程机器,
# tcrmgr copy -port 11211 remotehost /data/backup.tch
备份文件将保存在remotehost的/data/backup.tch
接下来恢复数据就比较简单,直接替换掉原有ttserver的数据文件,启动就可以了。
这种方式适用于定期的数据备份,在出现灾难故障时可以恢复到某一个时间的数据。不适合用来增加从库时需要的数据库文件。
2.如何不停机增加从库
从库需要进行同步,那么就需要有个文件的时间版本,防止数据冲突。
首先我们建立一个一个如下的脚本文件,存为"backup.sh",并赋予执行权限(chmod 755 backup.sh)。比如存在:/data/backup/路径下。
#! /bin/sh
srcpath="$1"
destpath="$1.$2"
rm -f "$destpath"
cp -f "$srcpath" "$destpath"
接下执行如下命令,执行的时间会根据你的磁盘性能和数据大小而定。
tcrmgr copy -port 11211 masterhost '@/data/backup/backup.sh'
materthost:主库主机名,请注意:backup.sh存放的路径是在materthost机器上。
'@/data/backup/backup.sh' :如果tcrmgr copy命令中,参数以@开始,那么后面的字符串作为命令行执行。
执行完成后,我们进入ttserver的数据目录,执行ls -lh会发现类似下面的文件名,
-rw-r--r-- 1 root root 9.2G Aug 25 14:31 casket.tch.1251181588942889
请确认产生casket.tch.xxxxx类似的文件名,xxxxx代表时间戳。
接下来在从库salve上以我们备份的文件来运行ttserver,把时间错写入到一个时间戳文件ttserver.rts。
$ ls
$ cp casket.tch.xxxxx casket.tch
$ echo xxxxx >ttserver.rts
$ mkdir ulog
$ ttserver -mhost masterhost -mport mport -port 11211 -ulog ulog -sid 2 -rts ttserver.rts casket.tch
运行后,ttserver将会以此时间戳进行同步。
masterhost :主库主机名
mport : 主库端口号
到此我们就完成了一个salve从库ttserver的增加。
3.小结
推荐备份也使用2中用到的方式,上面带上了时间戳,可以精确的知道数据的版本时间。
另外请注意:在使用此方法进行备份的时候,ttserver会在备份过程中一直保持同步阻塞和不修改数据。所以可以保证备份出来的版本跟时间戳的一致性。
Tokyo Tyrant(TTServer)系列-数据压缩
由于忙于工作,好久继续写关于ttserver的东西了。最近由于服务器准备的原因,只能在32位上做ttserver的测试,很快数据就达到 2G,ttserver无法正常工作,于是想到了ttserver的压缩功能,发现压缩比例挺大。所以进行了一些测试并在项目中做了一些应用。本文将展示 在64下面进行压缩的压缩比以及进行压缩的好处。
压缩测试
数据:2720268条原始新闻数据,每条数据使用json格式进行存储。
A机器ttserver配置:casket.tch#bnum=100000000#xmsiz=524288000#rcnum=200000#opts=ld
B机器ttserver配置:casket.tch#bnum=100000000#xmsiz=524288000#rcnum=200000
分别把原始新闻数据存储A机器和B机器。其中A和B的ulog日志文件大小都为19G。接下来来看ttserver的数据库文件大小,
A机器(有压缩)6.1G,B机器 (无压缩)17G。压缩后大概只占原来文件的1/3。
配置中的#opts=ld的d表示使用压缩。关于opts可以参考官方的原话:
"opts" can contains "l" of large option, "d" of Deflate option, "b" of BZIP2 option, and "t" of TCBS option.
经过初步测试,d是速度比较快的一种了。
压缩的优点
存储空间,压缩首先给人带来的优点肯定就是节约存储空间,这点在服务器空间不足的情况下使用非常有用,当然,你在32位2G文件大小的限制下,使用压缩的话就可以存储更多的数据。
IO性能:经过压缩,数据本身变得小了,对磁盘的IO也会相应减小,如果你的磁盘IO对你的应用形成了瓶颈,那么压缩也是可以为你来带益处的。对于IO的性能提高在硬盘结构和工作方式上也能得到解释。
压缩的缺点
使用压缩肯定就会耗费CPU资源了,所以CPU和空间只是一个权衡,根据经验,一般来说使用压缩都是没有问题的。比如nginx的gzip压缩静态文件(js,css)。
ttserver的压缩跟memcached的压缩的比较
提交到了比较,肯定就有不一样的地方。ttserver使用了内部压缩,就是服务器端(ttserver)负责压缩。而memcached的压缩则是客户端进行的,memcached只是负责存储压缩后的数据。客户端client根据flag参数来确定是否解压。ttserver是服务器负责压缩,memcache是客户端负责压缩。
ttserver输出的是解压后的数据,memcached输出的就是输入的压缩数据(数据使用压缩的情况)。这样就形成一个区别,memcached使用压缩后,由于输出的是压缩数据,会降低网络传输,而ttserver则不会有任何改变。
关于memcached的使用请网上搜索相应的介绍。
请注意Tokyo Tyrant (ttserver)在大数据量下的不稳定
ttserver不稳定案例
1. CMS a系统的文章采用了ttserver存储。在数据达到30多G的时候,经常出现写入失败,还出现了几次意外崩溃,无法重启成功,只得从slave恢复数据。
2.CMS b系统的图片使用ttserver存储,在数据导到65G的时候出现无法写入的情况,重启后问题依旧,只得从slave重新恢复数据重启。
3.BBS系统采用ttserver做缓存,设计上采用如果没有更新,那么缓存永久存在的策略。在数据达到65GB,数据条数在700多万条的时 候,出现大量写入失败的情况,系统负载开始上升,日志出现大量do_mc_set: operation failed。当然这里作为缓存比较好处理,删掉,重新建个新的就OK。(注:启动参数 data.tch#bnum=10000000#xmsiz=434217728#rcnum=20000)
测试中ttserver写入表现不稳定
1.#bum=10000000
插入940多万数据(一条7.2k)时出现崩溃(测了两次都一样,看起来好像内部出现了死锁,连上后,无法进行任何响应,没有任何操作时,也占了大量CPU)。越到后面插入的qps(每秒响应数)越小。而且波动比较大。
#bum=100000000
可以顺利插入上千万的数据,但是越到后面qps越小。越到后面插入的qps(每秒响应数)越小。而且波动比较大。
2.跟其他的nosql(mongodb,bdb je,cassandra)对比测试,在写入上,ttserver是表现最不稳定的,其他的nosql都非常好。
总结和注意
1.经过对Tokyo Cabinet 的测试,同样跟ttserver一样,所以应该是Tokyo Cabinet 导致的不稳定。在选择btree方式存储时,随着数据量的增加一样不稳定。在优化参数上也做了各种尝试。
2.ttserver在性能的表现上非常不俗,特别是内存占用和cpu占用都很低,能同时响应上万的并发。但是你应该注意,他一般在数据导到20G以上就会出现不稳定情况。
所以用ttserver来存储单条比较小的数据非常好,存储大文本或者大的二进制文件,由于空间占用上升很快,很快就会变得不稳定。
3.注意备份,使用master-slave是个非常好的主意,在ttserver崩溃导致文件损坏或者其他什么原因无法启动时,你可以从slave 拷贝数据文件来进行恢复。
4.如果你一定要使用ttserver,建议对数据进行分片(sharding)存储,或者你自己使用一个网络接口,底层使用Tokyo Cabinet 来进行分片存储。
5.以上只是个人在使用中遇到的情况,本人正在尝试在存储大文本的ttserver进行替换掉。
Tokyo Tyrant (ttserver)的master-slave复制协议分析
The replication protocol of Tokyo Tyrant (ttserver)
[文章作者:孙立 链接:http://www.cnblogs.com/sunli/ 更新时间:2010-06-26]
目的
ttserver已经自带了主从复制功能,而且运行非常稳定,高效,使我们在使用ttserver实现高可靠性的不二选择。为什么我还要分析它的复制协议呢?
1.需要实时从ttserver同步数据到一个异构库。比如mysql,其他的nosql数据库。
2.数据的无缝迁移,如果需要从ttserver数据库无缝切换到其他数据库,可以使用这种复制协议
3.高性能的异步处理队列,你可以设置主库为mem类型,然后使用同步协议获取数据,这实际上就是一个队列,而且还是一个持久化的队列服务。
4.其他存储写一个服务,可以用ttserver做slave。
协议结构分析
咱们从数据流向的流程开始:
1. 客户端(slave)连接到服务器端(master)
2. slave连接成功后向master发送
+--------------------------------------+
|0xC8 |0xa0 | slave rts | slave sid |
|1byte |1 byte | 8 bytes | 4 bytes |
+--------------------------------------+
3. master收到后,想客户端发送:
+---------+
|mid |
|4 bytes |
+---------+
4. slave收到后可以得到服务器端的master sid.
5. 这里就开始复制了,master继续想客户端循环不断的发送复制的数据的object.
+------+
|0xca | 表示没有任何操作
|1 byte|
+------+
发送一个操作项:
+--------------------------------------------------+
|0xc9 |rts | rsid |rsize |data |
|1 byte |8 bytes |4 bytes |4 bytes |rsize bytes |
+--------------------------------------------------+
其中data的结构:
+-----------------------------------+
|magic |cmd |[data] |
|1 bytes |1 bytes | key-value data |
+-----------------------------------+
cmd表示各种操作类型,比如put putkeep 等
6. slave循环接受数据进行数据ok了。
协议实现
ttserver的复制协议非常简单,因为官方并没有把复制协议写到文档中,其他操作都有文档的。就需要去分析它的C代码,结构分析出来实现就非常简单了。 我会开放一些实现,到时会在www.cnblogs.com/sunli/公布
Tokyo(ttserver)使用手册摘要
1 概述
Tokyo是Tokyo Cabinet和Tokyo Tyrant的简称,合在一起用也称ttserver。
Tokyo Cabinet 是日本人 平林幹雄 开发的一款 NoSQL 数据库,数据库由一系列key-value对的记录构成,类似bdb。
Tokyo Tyrant 是由同一作者开发的 Tokyo Cabinet 数据库网络接口。它拥有Memcached兼容协议,也可以通过HTTP协议进行数据交换。Tokyo Tyrant 加上 Tokyo Cabinet,构成了一款支持高并发的分布式持久存储系统Tokyo。
对Tokyo内部机制感兴趣的请参考陈海涛 chenht@ucweb.com:《Tokyo代码剖析》;
针对使用tt时出现太多误用,参数误设或未设,提供使用手册的摘要。在此开一个讨论的头。
2 Tokyo的安装
测试了在32位机器和64位机器都运行正常,64位机器可以支持>2G的单个db文件;
32位机器加上编译选项” --enable-off64”后也能支持>2G的单个db文件,但是不能突破32位Linux 3G用户内存空间的限制,所以内存最大只能用3G的,除非安装64位操作系统。
可用普通用户安装和运行。
Tokyo Cabinet依赖下面的库,一般Linux会自带,编译出错的话则需先安装:
zlib : 用来压缩. 1.2.3版本或更新的.
bzip2 : 用来压缩. 1.0.5版本或更新的.
下面的例子都是基于$HOME/local目录,使用时可更改。
下载最新的包(注意别下载到旧包了),2010年8月推荐用的最新版本是:
http://1978th.net/tokyotyrant/Latest Source Package (version 1.1.41)
http://1978th.net/tokyocabinet/Latest Source Package (version 1.4.46)
注:新版本主要进行bugfix,请尽量下载最新版本,changelog在源代码包里面。
下载后传到Linux的目录解压:
tar zxvf ***.tar.gz
2.1 Tokyocabinet
cd tokyocabinet-***
32位操作系统:
./configure --prefix=$HOME/local/tokyocabinet/ --enable-off64
64位操作系统:
./configure --prefix=$HOME/local/tokyocabinet/
make
make install
2.1.1 32位操作系统支持大于2G的db文件
32位操作系统要支持大于2G的db文件请加上” --enable-off64”,否则会导致严重问题,db文件超过2G时表现为:
Tcrmgr inform显示记录数为0,实际数据并没有被清空;
连接暴多但都操作失败,ttserver.log内提示“ERROR ttacceptsock failed”和“ERROR do_mc_set: operation failed”等;
Ttserver检测到文件异常会悄悄退出。
2.2 Tokyotyrant
环境变量设置,cd $HOME 后vi .bash_profile,修改PATH和LD_LIBRARY_PATH加上Tokyo的相关安装路径:
PATH=$HOME/local/tokyocabinet/bin:$HOME/local/tokyotyrant/bin:$PATH
LD_LIBRARY_PATH=$HOME/local/tokyocabinet/lib:$HOME/local/tokyotyrant/lib:$LD_LIBRARY_PATH
export PATH
export LD_LIBRARY_PATH
然后安装:
./configure --prefix=$HOME/local/tokyotyrant \
--with-tc=$HOME/local/tokyocabinet
make
make install
安装后在$HOME/local目录下生成了安装目录:
cd $HOME/local/tokyotyran
mkdir log data
新建两个目录用来存放ulog和db文件等。
在两台主机都安装完后,于是可以执行下面的启动步骤了。
2.2.1 支持lua脚本
末尾加上–enable-lua表示支持lua脚本:
./configure --prefix=$HOME/local/tokyotyrant \
--with-tc=$HOME/local/tokyocabinet –enable-lua
2.3 版本查看
查看tc版本:
tcamgr --version
查看tt版本:
ttserver --version
3 Tokyo的启动
生产环境可用本例的目录结构,可将#后面的参数再调整。
3.1 Hash关键性能参数
Hash是B+tree的基础,数据put时直接写入文件或文件映射,并非写缓存,是比较安全的数据存储方式。数据量小时,全在缓存或内存映射内操作,读写很快。
而且写数据是单条写入,所以数据量超过内存映射xmsiz时后要直接写入db文件,性能下降明显,io升高明显。
"bnum", 用来保存计算完hash值后的每个key在db文件的位置,bnum太小时hash值冲突比例就大。冲突的key依次链接起来,查找时增加了搜寻次数;
该值持久化到db文件,全映射在内存,默认很小是131071,最大可以设几亿以上。,要减少hash冲突次数,则要设置bnum >= key个数,一般一年后key要达到5000万个,bnum则设置为5千万:50 000 000。
"opts", 指定压缩方式(hash的短数据压缩比不高)和bucket array对每条数据用4字节还是8字节保存文件偏移量,要支持db文件>2G请加“#opts=l”。要支持db文件>2G并且用效果较好的gzip用到的压缩算法请加“#opts=ld”。
hash方式单条数据很短(< 100字节)时压缩效果差,可以不用这个参数,否则请带上这个参数,但会占用更多cpu。
"rcnum", hash map缓存的记录数,get时放到这个缓存,set时从缓存清掉该key,默认0不缓存,设置则最小256,B+tree不用这个参数,缓存热点数据的,在get访问确定没明显热点时不要设置这个参数;在有明显热点时才需设置这个参数,在保证xmsiz足够大时这个参数推荐设小些,例如100万,因为会把rnum条key和value不加压缩地放内存,除非机器内存很充裕。
"xmsiz",指定文件映射尺寸,默认且最小为:256(放head等关键信息)+ bucket array的尺寸。注意这个最重要的参数必须>=db文件尺寸才能正常速度地响应,否则很慢,例如db文件最大会达到10G,则xmsiz设置为10G,单位字节。
上述参数中只有这个xmsiz参数在启动后还可通过重启调整。
3.2 B+tree关键性能参数
B+tree是基于hash机制实现的,复用上述的db文件格式和文件映射,不同的只是最上层缓存机制。
写入db数据时,是按叶节点或非页节点进行了打包分页,整页写入;压缩也是整页压缩,压缩比更高。写也进行了缓存。
但必须在备机上定期执行tcrmgr sync,否则异常重启丢掉数据。
"bnum", 同hash方式的,但bnum的数量大于或等于存储总记录数的1/128即可,因为b+tree是整页保存到hash db内。
"opts", 同hash方式的该选项,要支持db文件>2G请加“#opts=l”。要支持db文件>2G并且用效果较好的gzip压缩算法请加“#opts=ld”。
b+tree方式压缩是整页(128条记录)压缩,压缩效果很好,数据量大时用b+tree时带上压缩参数降低内存使用量效果明显,但会稍占用更多cpu。
"xmsiz",同hash方式的。
"lcnum", b+tree缓存叶节点数,每个叶节点上可放128条记录作为一页,减轻读写压力,缓存热点数据的,默认1024,设的话最小64,太大则stop和sync时耗时很多。在xmsiz足够大时这个参数别设置。
"ncnum", b+tree缓存非叶节点数,每个树节点上可放256条索引作为一页,索引指向叶节点,减轻读写压力, 缓存热点数据,默认512,设的话最小64,太大则stop和sync时耗时很多。通常为叶节点数的一半。
在xmsiz足够大时以上两个参数可不设置。
#define BDBDEFLCNUM 1024 // default number of leaf cache
#define BDBDEFNCNUM 512 // default number of node cache
3.3 Hash主-备启动命令
./ttserver -host 192.168.4.150 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 91 $HOME/local/tokyotyrant/data/database.tch#bnum=10000000#xmsiz=1024000000 #rcnum=1000000#opts=ld
./ttserver -host 192.168.4.151 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 92 -mhost 192.168.4.150 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tch#bnum=10000000#xmsiz=1024000000 #rcnum=1000000#opts=ld
3.4 B+tree主-主启动命令
./ttserver -host 192.168.4.150 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 91 -mhost 192.168.4.151 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tcb#bnum=10000000#xmsiz=2000000000 #lcnum=1024#ncnum=512#opts=ld
./ttserver -host 192.168.4.151 -port 11230 -thnum 8 -dmn -pid $HOME/local/tokyotyrant/bin/ttserver.pid -log $HOME/local/tokyotyrant/log/ttserver.log -le -ulog $HOME/local/tokyotyrant/data/ -ulim 128m -sid 92 -mhost 192.168.4.150 -mport 11230 -rts $HOME/local/tokyotyrant/data/ttserver.rts $HOME/local/tokyotyrant/data/database.tcb#bnum=10000000#xmsiz=2000000000 #lcnum=1024#ncnum=512#opts=ld
相关文章推荐
- Tokyo Tyrant(TTServer)系列-介绍、安装以及应用
- Tokyo Tyrant(TTServer)系列(一)-介绍和安装
- Tokyo Tyrant(TTServer)系列-介绍和安装
- Tokyo Tyrant(TTServer)系列-介绍和安装
- Tokyo Tyrant(TTServer)系列(一)-介绍和安装
- Tokyo Tyrant(TTServer)系列(一)-介绍和安装
- Tokyo Tyrant(TTServer)系列-介绍、安装以及应用
- Tokyo Tyrant(TTServer)介绍和安装 以及配置
- 还为安装IIS发愁吗?全系列IIS自动安装程序倾囊奉送!--技术原理介绍及成品下载
- 【Nunit入门系列讲座 1】Nunit的安装及功能介绍
- Dynamic CRM2013安装系列二、AD服务器基本介绍及配置
- [Python爬虫] scrapy爬虫系列 <一>.安装及入门介绍
- Vmware vSphere 5.0系列教程之三 vCenter介绍及安装配置
- Spark入门实战系列--10.分布式内存文件系统Tachyon介绍及安装部署
- redis系列:redis介绍与安装
- GREENPLUM系列介绍之安装
- ArcSDE安装介绍系列一
- Tokyo Tyrant(TTServer)系列-启动参数和配置
- Tokyo Tyrant(TTServer)系列(三)-Memcache协议
- Vmware vSphere 5.0系列教程之三 vCenter介绍及安装配置